int main()
{
union {
struct {
char c[2];
char ch[2];
} s;
struct {
int i;
int j;
} st;
} u = { (12, 1), (15, 1) };
printf("%d %d ", u.st.i, u.st.j);
}
上面怎么会打印“257 0”?
使用{}
而不是创建什么区别()
?
{}
表示初始化子对象。
()
是对表达式进行分组的运算符,例如(1+3)*2
. 您混淆了逗号运算符的使用,它丢弃了左侧的操作数并返回了右侧的操作数。(12,1)
是一样的1
。
初始化 aunion
总是设置它的第一个成员并忽略其他成员。这是因为一次只有一个成员可以存储一个值。
使用标量值初始化数组子对象,就像传递1
给 initialize一样c[2]
,会自动跳转到数组中。这称为大括号省略。接下来1
将初始化数组的第二个成员。
您分配1
给 中的每个字符c[2]
,然后将生成的字节字符串作为 little-endian 读回int
。数组ch[2]
根本没有显式初始化;在 C++ 中它会被设置为零,但我不完全确定在 C 中。
初始化程序{ {12, 1}, {15, 1} }
不起作用,因为显然,大括号省略解释第一个}
关闭整个union
.
初始化程序{{ {12, 1}, {15, 1} }}
将避免大括号省略并设置两个数组。{ 12, 1, 15, 1 }
应该做同样的事情。
请注意,标量值和字节字符串之间的转换是实现定义的;特别是它取决于字节顺序和大小int
。
两者都(12, 1)
简化(15, 1)
为(奇怪的是)1
。这是因为,正如 Omkant 所说,您使用的是逗号运算符,它执行它划分的每个表达式,但返回最终表达式的值。维基百科条目实际上很好地解释了这一点。
结果,u.s.c[0]
第一个 1u.s.c[1]
被填充,第二个 1 被填充。由于联合覆盖 intu.st.i
和u.c[2]
(u.ch[2]
假设 8 位字符和 32 位整数),并且架构是 little-endian (从您的结果中知道),您在 的最低字节中有u.st.i
一个 1,在它的第二低字节中有一个 1,其值为256*1 + 1 = 257
.
同时,没有值写入 的内存u.st.j
,因此第二个输出为 0。
what the difference will it create if i use {} instead of ().
如果您使用()
then ,则分配的值,
将Comma operator
是括号内最右边的值。
但在 is 的情况下{}
,
,Comma seperator
每个单独的值都分配给相应的成员。但在这种情况下,它不会编译并抛出错误:
extra brace group at end of initializer.
似乎您误解了联合的意义,联合中的对象共享它们的内存,因此您只能初始化其中一个对象而不是两者,换句话说,底层内存是相同的,并且如另一个答案中所述,始终初始化联合设置它的第一个成员,所以如果你想初始化第二个成员,你可以使用 C99 指定的初始化器:
u = {.st={15, 1} };
并初始化第一个结构中的数组:
u = { .s={{12, 1}, {15, 1}} };
或者没有.s
第一个结构:
u = { {{12, 1}, {15, 1}} };