Подтвердить что ты не робот

Инициализация анонимных структур или объединений в C1X

У меня возникает следующий вопрос: как правильно инициализируются анонимные структуры (или союзы) в соответствии с текущим проектом 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?

Большое спасибо!

UPDATE

Поскольку анонимные члены кажутся полезными только при смешивании структур/объединений, как правильно инициализировать это:

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

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

4b9b3361

Ответ 1

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) инициализируется как регулярный подагрегированный файл.

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

Ответ 2

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

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

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

Ответ 3

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

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