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

孤者浪人 提交于 2019-12-22 15:54:51

问题


Say I have a class/struct with a single union in it... something like:

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

What's the proper way to do an initializer list for this kind of data type?

Box iMyBoxA = { 10, 10, 100, 100 };
Box iMyBoxB = ( Box ){ 10, 10, 100, 100 };

The 'A' option above works in many cases, but isn't completely portable... giving the error "no known conversion for argument 1 from 'brace-enclosed initializer list'". And the second doesn't compile with "Cannot omit braces around initialization of subobject..."

I've tried a few other cases and can't seem to get it to compile across multiple platforms.


回答1:


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 } } };



回答2:


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.



来源:https://stackoverflow.com/questions/18411039/whats-the-proper-format-for-a-union-initializer-list

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