инициализация анонимных структур или союзов в C1X - PullRequest
19 голосов
/ 21 февраля 2011

У меня следующий вопрос: как правильно инициализируются анонимные структуры (или объединения) в соответствии с текущим 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, а в tcc g.j == 3 и g.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: </p>

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

Это дает ошибки в clang и tcc, но работает в gcc и icc:

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

Является ли второй нарушением стандарта?

Ответы [ 3 ]

6 голосов
/ 21 февраля 2011

f и h должны правильно инициализировать всех членов, поскольку i и j должны рассматриваться как члены struct foo (C1x 6.7.2.1 §13):

Члены анонимной структуры или объединения считаются членами содержащей структуры или объединения.

Я не думаю, что инициализация gcc для g правильна, учитывая C1x 6.7.9 §9:

За исключением случаев, когда явно указано иное, для целей настоящего подпункта неназванные члены объектов структуры и типа объединения не участвуют в инициализации.

§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) инициализируется как обычный субагрегат.

Если моя интерпретацияверно, анонимные структуры имеют смысл только в том случае, если они содержатся внутри объединения: анонимная структура в структуре неотличима от плоской структуры, содержащей дополнительные элементы.

1 голос
/ 21 февраля 2011

Все члены, которые имеют имена в вашей структуре, могут быть инициализированы. Вы просто не можете инициализировать промежуточные структуры как таковые. Но

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

должен это сделать.

0 голосов
/ 21 февраля 2011

Я не читал черновик, я уверен, что неназванные и анонимные участники разные.Безымянный будет что-то вроде

struct foo {
    int bar:1; /* named */
    int :31;   /* unnamed */
};
...