2015-04-28 41 views
6

Dlaczego następujący przykład nie działa w C?Anonimowa Unia 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: Przy okazji: t2.y = y; działa

+0

Teście T2 = {2, Y : y}; wydaje się działać w gcc – samgak

+0

definicji struct nie należy wpisywać. typedef tylko zaśmiecanie Kodeksu prowadzi do nieporozumień dla czytelnika ludzkiej i przestrzeń zaśmiecanie nazwa kompilator – user3629249

+0

mający Jedyna różnica między nazwą typu i nazwy instancji będącej kapitalizacja jest bardzo dobrym źródłem błędów, które są bardzo trudne do znalezienia . BTW: podczas pisania łańcucha inicjalizacyjnego wszystkie wartości muszą być stałe, a struktura y NIE jest stała. – user3629249

Odpowiedz

4

Ponieważ typ inicjatora nie są analizowane i porównywane z możliwych członków union.

Zamiast tego, jesteś po prostu ma zapewnić inicjator dla pierwszego union członka.

C11 projekt §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.

Jak wspomniano, można użyć desygnatorów kontrolować to:

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

powinien działać (to .y jest oznaczenie "nowy" w C99).

+0

Należy zatem zauważyć, że ten problem nie jest związany z anonimowymi strukturami/związkami jako takimi, lecz po prostu inicjacją unii. A ponieważ anonimowe struktury/związki wymagają C11, wyznaczone inicjatory będą działać dobrze. – Lundin

2

Musisz określić, że są inicjowanie członkowskim innym niż pierwszy:

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

przeciwnym razie kompilator będzie starał się go zainicjować jak gdybyś napisał: .x = y