20

次の質問があります。現在のC1Xドラフトに従って匿名構造(またはユニオン)を適切に初期化するにはどうすればよいですか?これは合法ですか:

struct foo {
    int a;
    struct {
        int i;
        int j;
    };
    int b;
};

struct foo f = { 1, 2, 3, 4 };
struct foo g = { 1, { 2 }, 3 };

GCCで、g.j == 0およびg.b == 3、tccg.j == 3およびでg.b == 0。現在のドラフトは次のように述べています。

「[...]構造体および共用体型のオブジェクトの名前のないメンバーは初期化に参加しません。構造体オブジェクトの名前のないメンバーは、初期化後も値が不確定です。」

これは本当に本当ですか?そうじゃない

struct foo h = { 0 };

すべてのメンバーを0に設定することになっていますか?

どうもありがとう!

更新

匿名メンバーは構造体/共用体を混合する場合にのみ役立つように思われるため、これを正しく初期化する方法は次のとおりです。

struct bar {
    int tag;
    union {
        double d;
        int i;
    };
};

?これにより、gcc<4.6およびicc11でエラーが発生しますが、gcc 4.6、icc 12、clang、およびtccで機能します。

struct bar a = { .tag = 1, .i = 42 };

これにより、clangとtccでエラーが発生しますが、gccとiccでは機能します。

struct bar b = { .tag = 1, { .i = 42 } };

2つ目は基準違反ですか?

4

3 に答える 3

6

f(C1x6.7.2.1§13)のメンバーのように扱われるためh、すべてのメンバーを正しく初期化する必要があります。ijstruct foo

匿名の構造体またはユニオンのメンバーは、それを含む構造体またはユニオンのメンバーと見なされます。

gC1x6.7.9§9を考慮すると、gccの初期化は正しくないと思います。

特に明記されていない限り、この節の目的上、構造体および共用体型のオブジェクトの名前のないメンバーは初期化に参加しません。

サブアグリゲートを扱う§20には、問題に関連する明示的なステートメントが含まれていないため、§9が適用されると思います(ただし、アグリゲート自体にのみ適用され、そのメンバーには適用されません!)。

肝心なのは、匿名のサブアグリゲートは個別のオブジェクトとして存在しないということです。つまり、tccの動作は正しいはずです...

この問題に関する私の見解のサンプルコード:

struct foo
{
    struct bar { int i; }; // (1) unnamed, but tagged, ie *not* anonymous
    struct { int j; };     // (2) unnamed, but anonymous
    struct { int k; } baz; // (3) named, but not tagged
};

(1)初期化に関与しない、(2)struct fooという名前の追加メンバーがあるかのように初期化jする、(3)通常のサブアグリゲートとして初期化する。

私の解釈が正しければ、匿名構造はユニオン内に含まれている場合にのみ意味があります。構造内の匿名構造は、追加のメンバーを含むフラット構造と区別できません。

于 2011-02-21T12:18:14.473 に答える
1

構造体に名前があるすべてのメンバーを初期化できます。中間構造自体を初期化することはできません。だが

struct foo f = { .a = 1, .i = 2, .j = 3, .b = 4 };

それをする必要があります。

于 2011-02-21T08:30:15.063 に答える
-1

私はドラフトを読んでいません。名前のないメンバーと匿名のメンバーは違うと確信しています。名前のないものは次のようになります

struct foo {
    int bar:1; /* named */
    int :31;   /* unnamed */
};
于 2011-02-21T08:14:18.773 に答える