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

在 GCCg.j == 0g.b == 3中,而在 tccg.j == 3g.b == 0. 目前的草案说:

“[...] 结构和联合类型对象的未命名成员不参与初始化。结构对象的未命名成员即使在初始化之后也具有不确定的值。”。

这真的是真的吗?不是吗

struct foo h = { 0 };

应该将所有成员设置为0?

非常感谢!

更新

由于匿名成员似乎只在混合结构/联合时才有用,如何正确初始化它:

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

? 这会在 gcc < 4.6 和 icc 11 中产生错误,但在 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 } };

第二个是否违反标准?

4

3 回答 3

6

f并且h应该正确初始化所有成员,i并且j将被视为struct foo(C1x 6.7.2.1 §13)的成员:

匿名结构或联合的成员被视为包含结构或联合的成员。

g考虑到 C1x 6.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 回答