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