Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 503
WaeCo Avatar asked Apr 28 '15 09:04

WaeCo


People also ask

How do you initialize a union in a struct?

When initializing an object of struct or union type, the initializer must be a non-empty, (until C23) brace-enclosed, comma-separated list of initializers for the members: = { expression , ... }

Can struct have Initializers?

Using designated initializers, a C99 feature which allows you to name members to be initialized, structure members can be initialized in any order, and any (single) member of a union can be initialized. Designated initializers are described in detail in Designated initializers for aggregate types (C only).

What is anonymous union in C++?

An anonymous union is a union without a name. It cannot be followed by a declarator. An anonymous union is not a type; it defines an unnamed object. The member names of an anonymous union must be distinct from other names within the scope in which the union is declared.

Can you initialize values in a struct?

No! We cannot initialize a structure members with its declaration, consider the given code (that is incorrect and compiler generates error).


2 Answers

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

like image 96
unwind Avatar answered Sep 29 '22 08:09

unwind


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

like image 23
2501 Avatar answered Sep 29 '22 09:09

2501