Pregunta

Ayer encontré un código de inicialización de estructura 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á la salida:

-> testFunc
test.first=1 test.second=2

Como puede ver, la estructura se inicializa correctamente. No sabía que las declaraciones etiquetadas pudieran usarse de esa manera. He visto varias otras formas 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 de C en línea. ¿Alguien sabe cómo y por qué funciona esto?

¿Fue útil?

Solución

Aquí está la sección del manual de gcc que explica la sintaxis de los inicializadores designados para estructuras y 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 aquí .

Tu compilador debería tener documentación similar.

Otros consejos

No son etiquetas ni campos de bits.

Esta es una sintaxis para inicializar los miembros de la estructura que se remontan a 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 se ve un poco diferente:

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };

Sí, como se señaló anteriormente, estos son inicializadores designados, que son estándar C, aunque debería cambiar a usar puntos en lugar de dos puntos. Y como observan, la mayoría de los libros todavía están bloqueados en algún lugar alrededor de 1984 en su sintaxis y no los mencionan. Más datos divertidos:

- Cuando se usan inicializadores designados, todo lo que no se especifica 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));

- También, puede usar la forma literal compuesta para usar esta forma en una línea de no inicialización, por ejemplo:

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

Estas son características realmente excelentes, y son compatibles con todos los compiladores de C en los que puedo pensar, ya que es el estándar. Es una pena que no sean tan conocidos.

En realidad no es "declaraciones etiquetadas", sino una forma de dar valores iniciales a los campos nombrados en la estructura.

Gcc da una advertencia sobre el uso obsoleto del inicializador designado con ':' " ;, y en C99 deberías escribir:

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

Esa sintaxis no está definida por el Estándar C. La sección 6.7.8 Inicialización 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 es (o está configurado para no ser) compatible con los estándares.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top