2015-04-28 17 views
6

Warum funktioniert folgendes Beispiel nicht in C?Anonymous Union in Struct Initialisierung

#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: By the way: t2.y = y;

+0

-Test t2 = {2, y : y}; scheint in gcc zu funktionieren – samgak

+0

struct definitionen sollten nicht typedef'd sein. der typedef stört nur den Code, führt zu Missverständnissen für den menschlichen Leser und verfälscht den Compiler-Namespace – user3629249

+0

da der einzige Unterschied zwischen einem Typnamen und einem Instanznamen die Großschreibung ist, ist eine sehr gute Quelle von Fehlern, die sehr schwer zu finden sind . BTW: Beim Schreiben einer Initialisierungszeichenfolge müssen alle Werte Konstanten sein und struct y ist KEINE Konstante. – user3629249

Antwort

4

Da die initializer des Typs funktioniert, ist nicht analysiert und abgeglichen gegen die möglichen Mitglieder des union.

Stattdessen sollten Sie einfach einen Initialisierer für das erste union-Mitglied bereitstellen. §6.7.9.17

C11 Entwurf:

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.

Wie bereits erwähnt, können Sie Bezeich verwenden steuern diese:

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

funktionieren soll (die .y ist ein Bezeichner, "neu" in C99).

+0

Es sollte also angemerkt werden, dass dieses Problem nicht mit anonymen Strukturen/Unionen als solcher zusammenhängt, sondern lediglich eine unionale Initialisierung. Und da anonyme Strukturen/Vereinigungen C11 erfordern, funktionieren die angegebenen Initialisierer gut. – Lundin

2

Sie müssen angeben, dass Sie ein anderes Element als das erste initialisiert wird:

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

Andernfalls wird der Compiler versuchen, es zu initialisieren, als ob Sie schrieb: .x = y