2009-10-21 13 views
34

私はループのために私を投げた構造体初期化コードを昨日見つけました。ここでは例があります:あなたが見ることができるようにラベルを使用したC構造体の初期化。それは動作しますが、どうですか?

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

、構造体が正しく初期化される:(私には)驚くべきことに

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); 
} 

、ここでは出力です。私はそのようなラベルを付けられたステートメントを使用することはできないことを認識していませ私は構造体の初期化を行ういくつかの他の方法を見てきましたが、私はオンラインCのFAQのいずれかでこの種の構造体初期化の例は見つかりませんでした。誰がどのように/なぜこの作品を知っていますか?

答えて

25

は、構造体と配列の両方の指定イニシャライザの構文を説明GCCマニュアルのセクションである:構造イニシャライザで

、 '.fieldnameと を初期化するために、フィールドの名前を指定します= 'となる。例えば、 次構造、

struct point { int x, y; }; 

次の初期化を与え

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

、ある

struct point p = { xvalue, yvalue }; 

GCC 2.5以降廃止されるのと同じ意味を有し、別の構文と等価です'フィールド名:'、ここに示すように:

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

該当するページはhereです。

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

+2

優秀でC++について何も言われません@Andrew –

+1

@AndrewCottrell、この "fieldname:"構文は私にとっては自然な(そして望ましい)、なぜそれが時代遅れと見なされるべきなのか考えていますか? – rick

+1

@rick "fieldname:"構文はgcc拡張であり、決してISO C標準には含まれていません。 – sigjuice

5

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

GCCは「『:』と指定イニシャライザの時代遅れの利用」に関する警告を与え、C99にあなたの代わりに書く必要があります。

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

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

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

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

、特定の構造体のメンバを初期化するための構文は、標準で初めて導入されたが、それは少し違うように見える:

typedef struct { int y; int x; } POINT; 
POINT p = { .x = 1, .y = 17 }; 
+0

はい、私は指定された初期化形式を知っていました。残念ながら、その形式はC++と互換性がありません! (とにかく私のテストではありません。)答えに感謝します。これが標準化されていないことを知っておくとよいでしょう。あなたがあなたの質問 –

+6

、そのドキュメントは明確な構文について説明します。 同じ意味を持つ別の構文を、GCC 2.5以降廃止され、 'フィールド名です:」、ここに示すように: 構造体点p = {y:y値、x:x値}; – horseyguy

3

構文はC標準で定義されていないこと。あなたのコンパイラは規格に準拠し、それはあなたのコンパイラがないことを意味し、診断メッセージなしのコロンで指定を受け付ける(またはではないと設定されている)場合は、セクション6.7.8 Initialization

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

を言います。ここ

9

はい、上記のように、これらは標準の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)); 

--Also、あなたが例えば、非初期化ライン上でこのフォームを使用する化合物リテラル形式を使用することができます。

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

これらは実際にあります優れた機能を持ち、私が考えることができるすべてのCコンパイラによってサポートされています。彼らがあまり知られていないことは残念です。

+1

代替コロン(コロンを使用)はとても自然で、私にとっては好ましいように見えますが、なぜコロンの代わりにピリオドを使用するべきかを明確にすることができますか? – rick

関連する問題