What's the proper format for a union initializer list?

十年热恋 提交于 2019-12-06 11:56:54

The original version of the structure and union definition in the question was:

struct Box { union { AS128 intr; AS32 a, b, c, d; } };

This is a little unusual. Assuming the types AS128 and AS32 are defined, then it is equivalent to:

struct Box1  // Renamed for convenience of testing
{
    union
    {
        AS128 intr;
        AS32  a;
        AS32  b;
        AS32  c;
        AS32  d;
    };
};

That is, it is a union of an AS128 called intr and 4 separate values of type AS32 called a, b, c and d (with the latter 4 all occupying the same space).

Presumably, what you have in mind is:

struct Box2
{
    union
    {
        AS128 intr;
        struct
        {
            AS32  a;
            AS32  b;
            AS32  c;
            AS32  d;
        } s;
    };
};

This uses the anonymous members feature of C11 (listed in the Foreword of ISO/IEC 9899:2011 as a new feature compared to C99). [The question has now been fixed to reflect more or less this notation (using an anonymous structure). Note that you can't directly designate an anonymous union member, so the s above is a good idea, at least. The structure without the s can be used, but I don't think you can initialize the structure unless you can designate it — you can only designate named elements of a union.]

With the first variant (struct Box1), you can initialize the first member (the AS128 intr; member) with no name:

struct Box1 b1 = { { 1234 } };

The outer braces are for the structure; the inner braces are for the (anonymous) union.

Or you can specify which member to initialize using a designated initializer:

struct Box1 b2 = { { .a = 1234 } };

Note that you can't do:

struct Box1 b3 = { { .a = 1234, .b = 2341 } };

The compiler gives a warning (see the example code below).

With the second variant (struct Box2), with the nested structure, you can still use the undesignated initializer or the designated initializers, but this time, you could specify all 4 of the members of the structure:

struct Box2 b4 = { { .s = { .a = 32, .b = 65, .c = 48, .d = 97 } } };

Example code

Using funny types for the AS128 and AS32 type names.

typedef long AS128;
typedef char AS32;

struct Box1
{
    union
    {
        AS128 intr;
        AS32  a;
        AS32  b;
        AS32  c;
        AS32  d;
    };
};

struct Box2
{
    union
    {
        AS128 intr;
        struct
        {
            AS32  a;
            AS32  b;
            AS32  c;
            AS32  d;
        } s;
    };
};

struct Box1 b1a = { { 1234 } };
struct Box1 b1b = { { .intr = 1234 } };
struct Box1 b1c = { { .a = 32 } };
//struct Box1 b1d = { { .b = 29, .c = 31 } }; // Invalid double initialization
//error: initialized field overwritten [-Werror=override-init]

struct Box2 b2a = { { 1234 } };
struct Box2 b2b = { { .intr = 1234 } };
struct Box2 b2c = { { .s = { .a = 29, .b = 30, .c = 31, .d = 32 } } };

A union holds only one member at a time, so you initialize it with only one value.

You may use Box iMyBoxA = { value }; to initialize the first-listed member of the union or Box iMyBoxA = { .name = value }; to initialize a particular member by name.

Some notes:

Your code is missing a semicolon after the union declaration; it should be:

struct Box { union { AS128 intr; AS32 a, b, c, d; }; };

Since you have a union inside a struct, you ought to use two sets of braces for the initializers:

Box iMyBoxA = { { value } };

The syntax with one set of braces is permitted but may elicit warnings from your compiler.

Designated initializers (member names in initializers) are a C 1999 feature. This question is tagged with C and C++. A C++ compiler might or might not accept a designated initializer. In C, you would also need to declare Box as a type using typedef or change Box iMyBoxA… to struct Box iMyBoxA….

In C, anonymous unions are new in C 2011.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!