7

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

4
  • Test t2 = { 2, y : y }; seems to work in gcc Commented Apr 28, 2015 at 9:20
  • struct definitions should not be typedef'd. the typedef only clutters the code, leads to misunderstandings for the human reader, and clutters the compiler name space Commented Apr 29, 2015 at 3:43
  • having the only difference between a type name and an instance name being the capitalization is a very good source of bugs that are very hard to find. BTW: when writing an initialization string, all values must be constants and struct y is NOT a constant. Commented Apr 29, 2015 at 3:46
  • 1
    @user3629249 Whether to typedef structs or not is a subjective style matter. There are two camps: the Linux camp, who think that they shouldn't be typedef:ed, and the everyone-else-camp who think they should. There's no obvious right or wrong here, so please don't start a style debate in comments. Commented Jun 22, 2015 at 11:05

2 Answers 2

8

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).

Sign up to request clarification or add additional context in comments.

1 Comment

So it should be noted that this problem isn't related to anonymous structs/unions as such, but merely plain union initialization. And since anonymous structs/unions require C11, designated initializers will work fine.
4

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.