结合内部的结构

时间:2012-12-19 07:49:08

标签: c struct unions

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"?

使用{}代替()会产生什么差异?

4 个答案:

答案 0 :(得分:14)

{}表示初始化子对象。

()是一个对表达式进行分组的运算符,例如(1+3)*2。您混淆地使用了逗号运算符,该运算符丢弃其左侧操作数并返回右侧操作数。 (12,1)1相同。

初始化union始终设置其第一个成员并忽略其他成员。这是因为一次只能有一个成员存储一个值。

初始化具有标量值的数组子对象,如通过1初始化c[2],会自动跳转到数组中。这称为大括号。下一个1将初始化数组的第二个成员。

您为1中的每个字符分配了c[2],然后将结果字节字符串作为little-endian int读回。数组ch[2]根本没有明确初始化;在C ++中,它将设置为零,但我不完全确定在C中。

初始化程序{ {12, 1}, {15, 1} }不起作用,因为显然,括号elision会解释第一个}以关闭整个union

初始化程序{{ {12, 1}, {15, 1} }}将避免括号缩写并设置两个数组。 { 12, 1, 15, 1 }也应该这样做。

请注意,标量值和字节字符串之间的转换是实现定义的;特别是它取决于字节顺序和int的大小。

答案 1 :(得分:3)

(12, 1)(15, 1)都简化为(奇怪的)1。这是因为,正如Omkant所说,你正在使用逗号运算符,它运行它所分割的每个表达式,但返回最终表达式的值。 Wikipedia entry实际上很好地解释了这一点。

结果,u.s.c[0]填充了第一个1,u.s.c[1]填充了第二个1.因为联合在u.st.iu.c[2]上覆盖了u.ch[2] u.st.i 1}}(假设8位字符和32位整数),并且架构是little-endian(从结果中得知),在256*1 + 1 = 257的最低字节中有1,在第二个字节中有1最低字节,值为u.st.j

同时,没有值写入{{1}}的内存,因此第二个输出为0.

答案 2 :(得分:0)

what the difference will it create if i use {} instead of ().

如果您使用的是(),则,将为Comma operator,并且指定的值将是括号内最右边的值。

但是如果{} ,Comma seperator,并且每个单独的值都分配给相应的成员。但在这种情况下,它不会编译并抛出错误:

extra brace group at end of initializer.

答案 3 :(得分:0)

似乎你误解了工会的观点,工会中的对象共享他们的记忆,所以你只能初始化其中一个对象而不是两者,换句话说底层内存是相同的,并且正如另一个答案中所提到的那样初始化union总是设置它的第一个成员,所以如果你想初始化第二个成员,你可以使用C99指定的初始化器:

u = {.st={15, 1} };

初始化第一个结构中的数组:

u = { .s={{12, 1}, {15, 1}} };

或者第一个结构没有.s

u = { {{12, 1}, {15, 1}} };