C言語において構造体の初期化を行うときには、定数式を並べる方法と、要素指示子を用いて初期値を指定する方法があります。要素指示子を用いた場合、メンバの識別子順とは順不同に初期値を記述することが出来、これはC++には存在しないC言語特有の構文となります。
struct st_id {
int a, b, c;
};
struct st_id v = { 1, 2, 3 };
// v.a = 1, v.b = 2, v.c = 3
struct st_id w = { .c=1, .b=2, .a=3 };
// w.a = 3, w.b = 2, w.c = 1
これら2つの初期化方法は組み合わせて用いることが出来、要素指示子での初期化は、以前の初期化子を書き換えることができます。
struct st_id x = { 1, 1, 1, .a = 2 };
// x.a = 2, x.b = 1, x.c = 1
この初期化方法はC言語の仕様として定義されており、C99のJIS規格「JISX3010-2003 プログラム言語C」1にて下記の通り記載されています。
6.7.8 初期化
<中略>
初期化は,初期化子並びの順に行う。特定の部分オブジェクトに対する初期化子が,同じ部分オブジェクトに対する以前の初期化子を書き換えることもある。
この初期化方法を使えば、構造体の初期化において、初期化指定されないメンバは通常ゼロ初期化されるところを、任意の初期値を指示することが出来ます。
例えば、関数マクロの可変長引数を使って下記の様に定義すれば、デフォルト初期値を持つ構造体宣言を行うマクロを定義できます。
# define MAKE_ST_ID(name, ...) \
struct st_id name = { -1, -1, -1, __VA_ARGS__ }
MAKE_ST_ID(y, .c = 0, .a = 3);
// y.a = 3, y.b = -1, y.c = 0