2009-12-11 62 views
5

Mam struct:Czy jest możliwe (legalne) przypisanie anonimowego związku w literale złożonym?

typedef struct _n 
{ 
    int type; 
    union { 
     char *s; 
     int i; 
    }; 
} n; 

Kiedy próbuję przypisać związek dosłowne, jak:

node n1 = {1, 0}; 
node n2 = {2, "test"}; 

gcc daje mi jakieś ostrzeżenia takie jak:

warning: initialization makes pointer from integer without a cast 
warning: initialization from incompatible pointer type 

Cóż, to wyjaśnij, że kompilator nie jest pewny, że przypisuję wartość potencjalnie niejednoznacznemu typowi. Jednakże, nawet jeśli staram się bardziej precyzyjnie określić:

node n0 = {type: 1, i: 4}; 

uzyskać:

error: unknown field ‘i’ specified in initializer 

Czytałem, że jeśli mogę umieścić (union <union name>) przed i: to może działać. Wolę jednak anonimowy związek. Czy jest jakiś sposób na zrobienie tego?

Odpowiedz

7

Anonimowe związki nie są standardem C - są rozszerzeniem kompilatora. Zdecydowanie polecam nadanie Unii nazwy. Jeśli upierasz się przy użyciu anonimowych unii, to można dać tylko inicjator dla pierwszego elementu go:

node n0 = {1, 0}; // initializes `s' to 0 

Kiedy skompilowany z -Wall -Wextra -pedantic, gcc dał mi ostrzeżenie „brakujące nawiasy wokół inicjator”, który jest prawidłowe ostrzeżenie. Inicjatora należy właściwie określić tak:

node n0 = {1, {0}}; // initializes `s' to 0 

Teraz to tylko daje ostrzeżenie, że „ISO C nie obsługuje nienazwanych elemencie/Zjednoczenia”.

Jeśli dasz Unii nazwę, a następnie można użyć funkcji C99 nazwie wyznaczone inicjalizatory zainicjować konkretne członkiem Unii:

typedef struct 
{ 
    int type; 
    union { 
     char *s; 
     int i; 
    } value; 
} node; 

node n0 = {1, { .s = "string"; }}; 
node n1 = {2, { .i = 123; }}; 

Trzeba unię mieć nazwę; w przeciwnym razie kompilator będzie narzekał na wskazany inicjator wewnątrz niego.

Składnia, której próbujesz użyć node n0 = {type: 1, i: 4}, jest nieprawidłową składnią; wygląda na to, że próbujesz użyć wyznaczonych inicjalizatorów.

+0

Zaskoczyło mnie to, gdy zobaczyłem go po raz pierwszy, ale do GCC, która jest właściwie legalną (choć przestarzałą) określoną składnią inicjalizującą. – ephemient

+0

że (myślę, że przestarzałe) składnia inicjalizatora dostałem od czytania kodu modułu jądra. Struktury "fops" są często pisane w ten sposób. Przejdę teraz na drogę C99. Szkoda w anonimowych związkach, nie wiedziałem, że nie są standardowe, dzięki za wyjaśnienie tego dla mnie. – Steve