entre - funciones con estructuras en c
Inicialización de estructuras anónimas o uniones en C1X. (3)
Tengo la siguiente pregunta: ¿Cómo se inicializan correctamente las estructuras anónimas (o sindicatos) de acuerdo con el borrador C1X actual? ¿Es esto legal?
struct foo {
int a;
struct {
int i;
int j;
};
int b;
};
struct foo f = { 1, 2, 3, 4 };
struct foo g = { 1, { 2 }, 3 };
En GCC, gj == 0
y gb == 3
, mientras que en tcc gj == 3
y gb == 0
. El borrador actual dice:
"los miembros sin nombre de los objetos de estructura y tipo de unión no participan en la inicialización. Los miembros sin nombre de los objetos de estructura tienen un valor indeterminado incluso después de la inicialización".
¿Puede esto ser realmente cierto? No es
struct foo h = { 0 };
¿Se supone que todos los miembros están en 0?
¡Muchas gracias!
ACTUALIZACIÓN :
Dado que los miembros anónimos solo parecen ser útiles al mezclar estructuras / uniones, cómo inicializar esto correctamente:
struct bar {
int tag;
union {
double d;
int i;
};
};
? Esto da errores en gcc <4.6 e icc 11, pero funciona en gcc 4.6, icc 12, clang y tcc:
struct bar a = { .tag = 1, .i = 42 };
Esto da errores en clang y tcc, pero funciona en gcc y icc:
struct bar b = { .tag = 1, { .i = 42 } };
¿Es el segundo una violación de la norma?
No he leído el borrador, estoy bastante seguro de que los miembros anónimos y anónimos son diferentes. Sin nombre sería algo como
struct foo {
int bar:1; /* named */
int :31; /* unnamed */
};
Todos los miembros que tienen nombres en su estructura pueden inicializarse. Simplemente no puedes inicializar las estructuras intermedias como tales. Pero
struct foo f = { .a = 1, .i = 2, .j = 3, .b = 4 };
Deberías hacerlo.
f
y h
deben inicializar correctamente todos los miembros, ya que i
y j
deben tratarse como miembros de struct foo
(C1x 6.7.2.1 §13):
Los miembros de una estructura o unión anónima se consideran miembros de la estructura que contiene o unión.
No creo que la inicialización de gcc de g
sea correcta, considerando C1x 6.7.9 §9:
Excepto cuando se indique explícitamente lo contrario, para los fines de esta subcláusula, los miembros sin nombre de los objetos de estructura y tipo de unión no participan en la inicialización.
El §20, que se ocupa de los subagregados, no contiene ninguna declaración explícita relevante para el problema, por lo que mi mejor conjetura sería que el §9 se aplica (¡pero solo al agregado en sí, no a sus miembros!).
La conclusión es que los subagregados anónimos no existen como objetos separados, es decir, el comportamiento de tcc debería ser correcto ...
Código de ejemplo para mi toma en el tema:
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) no toma parte en la inicialización, (2) se inicializa como si struct foo
tuviera un miembro adicional llamado j
, (3) se inicializa como un subagregado regular.
Si mi interpretación es correcta, las estructuras anónimas solo tienen sentido si están contenidas dentro de una unión: una estructura anónima dentro de una estructura es indistinguible de una estructura plana que contiene miembros adicionales.