Инициализация анонимных структур или объединений в 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 } };
Является ли второе нарушением стандарта?
Ответы
Ответ 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 */
};