2015-04-28 12 views
6

Perché l'esempio seguente non funziona in C?Anonimo Union in Struct Initializer

#include <stdio.h> 

typedef struct { 
    int x; 
} X; 

typedef struct { 
    char y[10]; 
} Y; 

typedef struct { 
    int pos; 
    union { 
    X x; 
    Y y; 
    }; 
} Test; 

int main() { 
    X x = { 65 }; 
    Y y = { "Hallo" }; 
    Test t = { 1, x }; // OK 
    printf("1: %d %d '%s'\n", t.pos, t.x.x, t.y.y); 
    Test t2 = { 2, y }; // ERROR 
    printf("2: %d %d '%s'\n", t2.pos, t2.x.x, t2.y.y); 
    Test t3 = { 3 }; // OK 
    printf("3: %d %d '%s'\n", t3.pos, t3.x.x, t3.y.y); 
    return 0; 
} 

main.c: In function ‘main’:
main.c:25:3: error: incompatible types when initializing type ‘int’ using type ‘Y’
Test t2 = { 2, y }; // ERROR
^

EDIT: A proposito: t2.y = y; funziona

+0

test t2 = {2, y : y}; sembra funzionare in gcc – samgak

+0

le definizioni di struct non dovrebbero essere digitate. il typedef ingombra solo il codice, porta a equivoci per il lettore umano e ingombra lo spazio dei nomi del compilatore – user3629249

+0

avendo l'unica differenza tra un nome di tipo e un nome di istanza essendo la maiuscola è una buona fonte di bug che sono molto difficili da trovare . BTW: quando si scrive una stringa di inizializzazione, tutti i valori devono essere costanti e struct y NON è una costante. – user3629249

risposta

4

Perché il tipo di inizializzazione non viene analizzato e confrontato con i possibili membri del union.

Invece, si suppone semplicemente di fornire un inizializzatore per il primo membro union.

C11 progetto §6.7.9.17:

Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.

Come accennato, è possibile utilizzare designatori per controllare questo:

Test t2 = { 2, .y = y }; 

dovrebbe funzionare (che .y è un designatore, "nuovo" in C99).

+0

Pertanto, è necessario notare che questo problema non è correlato a strutture/unioni anonime in quanto tali, ma semplicemente all'inizializzazione di una unione semplice. E poiché le strutture/unioni anonime richiedono C11, gli inizializzatori designati funzioneranno correttamente. – Lundin

2

bisogna specificare che si sta inizializzazione di un membro diverso dal primo:

Test t2 = { 2, { .y = y } } ; 

In caso contrario, il compilatore cercherà di inizializzarlo come se hai scritto: .x = y