WaeCo
WaeCo

Reputation: 1217

Anonymous Union in Struct Initializer

Why does following example not work in C?

#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; works

Upvotes: 7

Views: 3158

Answers (2)

2501
2501

Reputation: 25752

You have to specify that you are initializing a member other than the first:

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

Otherwise the compiler will try to initialize it as if you wrote: .x = y

Upvotes: 4

unwind
unwind

Reputation: 399793

Because the initializer's type isn't analyzed and matched against the possible members of the union.

Instead, you're simply supposed to provide an initializer for the first union member.

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

As mentioned, you can use designators to control this:

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

should work (that .y is a designator, "new" in C99).

Upvotes: 8

Related Questions