在C中与工会混淆

Adr*_*ian 2 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);
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么c这里的值为0?

unw*_*ind 6

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

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

int x, y;
x = 5;
y = 2;
y = 3;
x = 1;
int c = (x - y) + (y - x);
Run Code Online (Sandbox Code Playgroud)

这简化为c = (1 - 3) + (3 - 1),-2 + 2或者0.

请注意,这只是基于观察,这是编译器通常看起来如何实现联合,并且它解释了观察到的行为.它仍然未定义,你应该小心这样的代码.


vic*_*irk 5

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

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


NPE*_*NPE 5

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

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

int c = (x.a - x.b) + (y.a - y.b);
Run Code Online (Sandbox Code Playgroud)

由于在实践中x.ax.b共享相同的存储位置(所以做y.ay.b),这两个操作数+始终为零.