问题中结构和联合定义的原始版本是:
struct Box { union { AS128 intr; AS32 a, b, c, d; } };
这有点不寻常。假设定义了 AS128 和 AS32 类型,则等价于:
struct Box1 // Renamed for convenience of testing
{
union
{
AS128 intr;
AS32 a;
AS32 b;
AS32 c;
AS32 d;
};
};
也就是说,它是一个AS128
被调用的值和 4 个被调用的类型的单独值的联合,以及(intr
后4个都占用相同的空间)。AS32
a
b
c
d
大概,你的想法是:
struct Box2
{
union
{
AS128 intr;
struct
{
AS32 a;
AS32 b;
AS32 c;
AS32 d;
} s;
};
};
这使用了 C11 的匿名成员功能(在 ISO/IEC 9899:2011 的前言中列出作为与 C99 相比的新功能)。 [这个问题现在已经修复,或多或少地反映了这个符号(使用匿名结构)。请注意,您不能直接指定匿名工会成员,因此s
至少上面是一个好主意。可以使用没有的结构s
,但我认为除非你可以指定它,否则你不能初始化结构——你只能指定联合的命名元素。]
使用第一个变体 ( struct Box1
),您可以初始化AS128 intr;
没有名称的第一个成员(成员):
struct Box1 b1 = { { 1234 } };
外大括号用于结构;内大括号用于(匿名)联合。
或者您可以使用指定的初始化程序指定要初始化的成员:
struct Box1 b2 = { { .a = 1234 } };
请注意,您不能这样做:
struct Box1 b3 = { { .a = 1234, .b = 2341 } };
编译器会发出警告(请参见下面的示例代码)。
使用第二个变体struct Box2
(
struct Box2 b4 = { { .s = { .a = 32, .b = 65, .c = 48, .d = 97 } } };
示例代码
AS128
对和AS32
类型名称使用有趣的类型。
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 } } };