Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initialization of anonymous structures or unions in C1X

Tags:

I have the following question: How are anonymous structures (or unions) properly initialized according to the current C1X draft? Is this legal:

struct foo {
    int a;
    struct {
        int i;
        int j;
    };
    int b;
};

struct foo f = { 1, 2, 3, 4 };
struct foo g = { 1, { 2 }, 3 };

In GCC, g.j == 0 and g.b == 3, while in tcc g.j == 3 and g.b == 0. The current draft says:

"[...] unnamed members of objects of structure and union type do not participate in initialization. Unnamed members of structure objects have indeterminate value even after initialization.".

Can this be really true? Isn't

struct foo h = { 0 };

supposed to set all members to 0?

Thanks very much!

UPDATE:

Since anonymous members seem to be only useful when mixing structs/unions, how to initialize this correctly:

struct bar {
    int tag;
    union {
        double d;
        int i;
    };
};

? This gives errors in gcc < 4.6 and icc 11, but works in gcc 4.6, icc 12, clang and tcc:

struct bar a = { .tag = 1, .i = 42 };

This gives errors in clang and tcc, but works in gcc and icc:

struct bar b = { .tag = 1, { .i = 42 } };

Is the second one a violation of the standard?

like image 259
jmuc Avatar asked Feb 21 '11 07:02

jmuc


People also ask

How do you initialize a structure of a union?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).

How do you initialize a union variable?

Initializing Union Variableunion data { int var1; double var2; char var3; }; union data j = {10}; This statement initializes the union variable j or in other words, it initializes only the first member of the union variable j .

Can we initialize variable in union?

By definition, you simply can not initialize a union to have more than one value simultaneously because, by definition, a union can contain only one type of value at any one time.

Can we initialize union in C?

C allows you to initialize a union in two ways: Initialize a union by initializing the first member of a union. Or initialize a union by assigning it to another union with the same type.


2 Answers

f and h should correctly initialize all members, as i and j are to be treated like members of struct foo (C1x 6.7.2.1 §13):

The members of an anonymous structure or union are considered to be members of the containing structure or union.

I don't think that gcc's initialization of g is correct, considering C1x 6.7.9 §9:

Except where explicitly stated otherwise, for the purposes of this subclause unnamed members of objects of structure and union type do not participate in initialization.

§20 - which deals with sub-aggregates - contains no explicit statement relevant to the issue, so my best guess would be that §9 applies (but only to the aggregate itself, not to its members!).

The bottom line is that anonymous sub-aggregates don't exist as separate objects, ie tcc's behaviour should be correct...

Example code for my take on the issue:

struct foo
{
    struct bar { int i; }; // (1) unnamed, but tagged, ie *not* anonymous
    struct { int j; };     // (2) unnamed, but anonymous
    struct { int k; } baz; // (3) named, but not tagged
};

(1) takes no part in initialization, (2) initializes as though struct foo had an additional member named j, (3) initializes as a regular sub-aggregate.

If my interpretation is correct, anonymous structures only make sense if contained within a union: an anonymous structure within a structure is indistinguishable from a flat structure containing additional members.

like image 166
Christoph Avatar answered Sep 24 '22 03:09

Christoph


All members that have names in your structure can be initialized. You just can't initialize the intermediate structures as such. But

struct foo f = { .a = 1, .i = 2, .j = 3, .b = 4 };

should do it.

like image 33
Jens Gustedt Avatar answered Sep 24 '22 03:09

Jens Gustedt