web-dev-qa-db-ja.com

ラベルを使用したC構造体の初期化。動作しますが、どのように?

昨日、ループを引き起こした構造体の初期化コードを見つけました。次に例を示します。

typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
    TEST_STRUCT test = {
        second: 2,
        first:  1
    };
    printf("test.first=%d test.second=%d\n", test.first, test.second);
}

驚いたことに(私にとって)、出力は次のとおりです。

-> testFunc
test.first=1 test.second=2

ご覧のとおり、構造体は適切に初期化されます。ラベル付きステートメントがそのように使用できることを知りませんでした。構造体の初期化を行う他の方法をいくつか見てきましたが、オンラインC FAQのいずれにもこの種の構造体の初期化の例は見つかりませんでした。誰がどのように/なぜこれが機能するのか知っていますか?

40
Andrew Cottrell

これは、構造体と配列の両方の指定された初期化子の構文を説明するgccマニュアルのセクションです。

構造イニシャライザでは、初期化するフィールドの名前を、要素値の前に「。fieldname =」で指定します。たとえば、次の構造が与えられた場合、

 struct point { int x, y; };

次の初期化

 struct point p = { .y = yvalue, .x = xvalue }; 

に等しい

 struct point p = { xvalue, yvalue }; 

GCC 2.5で廃止された同じ意味を持つ別の構文は、次のように 'fieldname:'です。

 struct point p = { y: yvalue, x: xvalue };

関連するページは here にあります。

コンパイラにも同様のドキュメントが必要です。

38
sigjuice

これらはラベルでもビットフィールドでもありません。

これは、C99より前の日付までの構造体メンバーを初期化する構文です。標準化されていませんが、たとえばgcc。

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };

C99では、特定の構造体メンバーを初期化するための構文が標準で初めて導入されましたが、外観が少し異なります。

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
33
ndim

はい、上で指摘したように、これらは指定された初期化子であり、標準Cです。ただし、コロンではなくピリオドを使用するように切り替える必要があります。また、ご存じのとおり、世の中に出回っている書籍のほとんどは、1984年ごろに構文が残っており、言及していません。より楽しい事実:

-指定されたイニシャライザを使用する場合、指定されていないものはすべてゼロで初期化されます。これは、非常に大きな構造体に役立ちます。例:

typedef struct {
   double a, b, c, d, e;
   char label[100];
} too_many_type;

too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));

-また、複合リテラル形式を使用して、非初期化行でこの形式を使用することもできます。例:

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

これらは本当に素晴らしい機能であり、私が考えることができるすべてのCコンパイラーによってサポートされています。彼らがあまり知られていないのは残念だ。

12
bk.

これは実際には「ラベル付きステートメント」ではなく、構造体の名前付きフィールドに初期値を与える方法です。

Gccは「指定されたイニシャライザを ':'とともに使用することの廃止」に関する警告を出します。C99では、代わりに次のように記述する必要があります。

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

この構文はC標準では定義されていません。セクション 6.7.8 Initialization言う

         designation:
                designator-list =
         designator-list:
                designator
                designator-list designator
         designator:
                [ constant-expression ]
                . identifier

コンパイラーが診断メッセージなしでコロン付きの指定を受け入れる場合、コンパイラーが標準に準拠していない(または構成されていない)ことを意味します。

3
pmg