web-dev-qa-db-ja.com

タグ付き構造の初期化構文とは何ですか?

struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};

この宣言では、標準のCタグ付き構造の初期化構文を使用しています。

誰かが詳しく説明できますか?

43
httpinterpret

「従来の」ANSI C言語(C89/90)で集約イニシャライザ({}のイニシャライザ)を使用する場合は、最初から順に、各構造体メンバーに個別のイニシャライザを指定する必要があります。例えば

struct S { int a, b, c, d; };

struct S s = { 1, 2, 3, 4 };
/* 1 for `s.a`, 2 for `s.b` and so on... */

すべてのメンバーの初期化子を指定する必要はありません。つまり、いつでも停止できます(残りのメンバーはゼロで初期化されます)。

何らかの理由で構造体の3番目のメンバーを明示的に初期化することだけに関心がある場合は、最初と2番目のメンバーに「ダミー」の明示的な初期化子を指定する必要がありました(目的の3番目に到達するためだけ)

/* We only care to explicitly initialize `s.c` */
struct S s = { 0, 0, 3 };
/* but we have to explicitly initialize `s.a` and `s.b` as well */

または特定の初期化を完全に中止し(ジェネリック= { 0 }で置き換える可能性が高い)、特定のメンバーへの後続の割り当てを使用する

struct S s = { 0 };
s.c = 3;

この割り当てベースのアプローチの注目すべき利点の1つは、struct Sの宣言におけるメンバーcの位置から独立していることです。

C言語(C99)の新しい仕様では、{}内で目的のメンバー名を指定することにより、「タグ付き」初期化子を使用できます。

struct S s = { .c = 3 };

このようにして、必要なメンバーを明示的に初期化するだけです(残りをゼロ初期化するようにコンパイラーに指示します)。これにより、タイピングの手間が省けるだけでなく、構造体型宣言でメンバーが指定されている順序から集約初期化子が独立します。

おそらくご存知のように、集約イニシャライザは配列でも使用できます。また、C99は配列による「タグ付き」初期化もサポートしています。配列の場合に「タグ」がどのように見えるかを次の例で示します

int a[10] = { [5] = 3 };
/* `a[5]` is initialized with 3, the rest of `a` is zero-initialized */

C言語が集約の初期化に対して「オールオアナッシング」アプローチに固執し続けることにもう一度注目する必要があります。構造体または配列の1つ(またはいくつか)のメンバーだけに明示的な初期化子を指定すると、集約全体が取得されます。初期化され、明示的な初期化子のないメンバーはゼロで初期化されます。

80
AnT

構造体のメンバーの名前を使用して、構造体を初期化しています。つまり、各メンバーの初期化には、そのメンバーの名前が「タグ付け」されます。

4
user23743

このタイプの初期化に関して言及する価値のあるもう1つの利点は、構造体メンバーの並べ替えが可能になることです。たとえば、同じハードウェアキャッシュラインに頻繁にアクセスされるメンバーへのポインターを配置することで、パフォーマンスが向上する場合があります。

1
Guy Avraham