example - Inicialización de C struct usando etiquetas. Funciona, pero ¿cómo?
structs in java (5)
Ayer encontré un código de inicialización de estructuras que me lanzó a un bucle. Aquí hay un ejemplo:
typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
TEST_STRUCT test = {
second: 2,
first: 1
};
printf("test.first=%d test.second=%d/n", test.first, test.second);
}
Sorprendentemente (para mí), aquí está el resultado:
-> testFunc
test.first=1 test.second=2
Como puede ver, la estructura se inicializa correctamente. No sabía que las declaraciones etiquetadas pudieran usarse así. He visto varias otras maneras de hacer la inicialización de estructuras, pero no encontré ningún ejemplo de este tipo de inicialización de estructuras en ninguna de las preguntas frecuentes en línea de C. ¿Alguien sabe cómo / por qué esto funciona?
Aquí está la sección del manual de gcc que explica la sintaxis de los inicializadores designados tanto para las estructuras como para las matrices:
En un inicializador de estructura, especifique el nombre de un campo para inicializar con '' .fieldname = '' antes del valor del elemento. Por ejemplo, dada la siguiente estructura,
struct point { int x, y; };
la siguiente inicialización
struct point p = { .y = yvalue, .x = xvalue };
es equivalente a
struct point p = { xvalue, yvalue };
Otra sintaxis que tiene el mismo significado, obsoleta desde GCC 2.5, es '' fieldname: '', como se muestra aquí:
struct point p = { y: yvalue, x: xvalue };
La página relevante se puede encontrar here .
Tu compilador debería tener documentación similar.
Esa sintaxis no está definida por el estándar C. Sección 6.7.8 Initialization
dice
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
Si su compilador acepta una designación con dos puntos sin un mensaje de diagnóstico, significa que su compilador no está (o no está configurado) Cumple con los estándares.
Estas no son etiquetas ni bitfields.
Esta es una sintaxis para inicializar los miembros de la estructura que data de los días anteriores a C99. No está estandarizado, pero está disponible en, por ejemplo, gcc.
typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
En C99, la sintaxis para inicializar miembros de estructuras específicas se introdujo por primera vez en un estándar, pero tiene un aspecto un tanto diferente:
typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
No se trata realmente de "declaraciones etiquetadas", sino de una forma de dar valores iniciales a los campos nombrados en la estructura.
Gcc da una advertencia sobre "uso obsoleto del inicializador designado con '':''", y en C99, en su lugar, debe escribir:
TEST_STRUCT test = {
.second = 2,
.first = 1
};
Sí, como se señaló anteriormente, estos son los inicializadores designados, que son C estándar, aunque debe cambiar a usar períodos en lugar de dos puntos. Y como usted nota, la mayoría de los libros que hay por ahí todavía están en algún lugar alrededor de 1984 en su sintaxis y no los mencionan. Más hechos divertidos:
- Al usar los inicializadores designados, todo lo no especificado se inicializa en cero. Esto ayuda con estructuras excepcionalmente grandes, por ejemplo:
typedef struct {
double a, b, c, d, e;
char label[100];
} too_many_type;
too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));
--Además, puede usar el formulario literal compuesto para usar este formulario en una línea que no sea de inicialización, por ejemplo:
too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};
Estas son características realmente geniales, y son compatibles con todos los compiladores de C que se me ocurren, ya que es el estándar. Es una pena que no sean tan conocidos.