在C中与工会混淆

时间:2011-12-01 12:40:33

标签: c

关于这段代码的简单问题:

union MyUnion
{
    int a;
    int b;
};

union MyUnion x, y;
x.a = 5;
y.b = 2;
y.a = 3;
x.b = 1;

int c = (x.a - y.b) + (y.a - x.b);

有人可以解释为什么c的值为0吗?

5 个答案:

答案 0 :(得分:6)

您只能访问联合的最后写入字段。此代码违反了此规范,因此会调用未定义的行为。

实质上,由于MyUnion.x和MyUnion.y共享相同的内存,您可以用以下代码替换代码:

int x, y;
x = 5;
y = 2;
y = 3;
x = 1;
int c = (x - y) + (y - x);

这简化为c = (1 - 3) + (3 - 1)-2 + 20

请注意,这只是基于以下观察:这是编译器通常似乎实现联合的方式,并且它解释了观察到的行为。它仍然是 未定义,你应该小心这样的代码。

答案 1 :(得分:5)

因为(1 - 3)+(3 - 1)= 0

联合中只有一个'值',它们都使用相同的内存位置,因此最后一个赋值就是值。

答案 2 :(得分:5)

这是未定义的行为。如果您上次写信至x.a,则不允许您阅读x.b,反之亦然。

实际上,您可以像这样重新安排表达式:

int c = (x.a - x.b) + (y.a - y.b);

由于实际上x.ax.b共享相同的内存位置(y.ay.b也是如此),+的两个操作数始终为零

答案 3 :(得分:3)

x和y都存储一个值,这是最后指定的值,因此x保持1,y保持3(该值保存在“a”和“b”成员中,因为它们的存储“重叠” “(这就是工会)。

所以等式为(1 - 3) + (3 - 1) = 0

是的,正如其他人评论的那样,行为是未定义的(取决于您的编译器,您可能得到不同的答案),但这是为什么您获得的值为0.

答案 4 :(得分:3)

int c =(1 - 3)+(3 - 1);

使用union时,只在内存中为一个变量创建空间,从而用最后一次使用的调用替换它的值。