我偶然发现了基于C中的工会的代码。这是代码:
union {
struct {
char ax[2];
char ab[2];
} s;
struct {
int a;
int b;
} st;
} u ={12, 1};
printf("%d %d", u.st.a, u.st.b);
我只是不明白输出是怎么来的268 0
。这些值是如何初始化的?
工会如何运作?输出不应该是12 1
。如果有人能够详细解释这里究竟发生了什么,那就太棒了。
我使用的是32位处理器和Windows 7。
答案 0 :(得分:17)
代码不符合你的想法。 Brace-initializes初始化第一个联盟成员,即u.s
。但是,现在初始化程序不完整并且缺少大括号,因为u.s
包含两个数组。它应该是一些思考:u = { { {'a', 'b'}, { 'c', 'd' } } };
你应该编译所有警告,一个体面的编译器应该告诉你有些不对劲。例如,GCC说missing braces around initialiser (near initialisation for ‘u.s’)
和missing initialiser (near initialisation for ‘u.s.ab’)
。非常有帮助。
在C99中,您可以利用命名成员初始化来初始化第二个union成员:u = { .st = {12, 1} };
(顺便说一下,这在C ++中是不可能的。)第一种情况的相应语法是{{1} },这可以说是更明确和可读!
答案 1 :(得分:4)
您的代码使用union的默认初始值设定项,它是第一个成员。 12和1都进入ax的字符,因此你看到的结果(这是非常依赖编译器的。)
如果你想通过第二个记忆(st
)进行初始化,你可以使用指定的初始值设定项:
union {
struct {
char ax[2];
char ab[2];
} s;
struct {
int a;
int b;
} st;
} u ={ .st = {12, 1}};
答案 2 :(得分:4)
代码集u.s.ax[0]
为12,u.s.ax[1]
为1. u.s.ax
重叠到u.st.a
,因此u.st.a
的最低有效字节设置为12和最重要的字节为1(所以你必须在小端架构上运行)给出值0x010C或268。
答案 3 :(得分:1)
它可能会将{12,1}分配给 s.ax 中的前2个字符。
因此在32位int中,它是1 * 256 + 12 = 268
答案 4 :(得分:1)
union的大小是组成union的最大元素的最大大小。因此,在这种情况下,您的联合类型在32位平台上的大小为8字节,其中int
类型各为4字节。但是,联合的第一个成员s
只占用2个字节,因此与st.a
成员的前2个字节重叠。由于您使用的是小端系统,这意味着我们将st.a
的两个低位字节重叠。因此,当您使用值{12, 1}
完成初始化联合时,您只是初始化st.a
的两个低位字节中的值...这样会留下{{1}的值初始化为st.b
。因此,当您尝试打印包含两个0
而不是int
成员的结构时,您最终会得到char
和128
的结果。