假设此代码段位于file.c中:
union numbers
{
int i;
float f;
};
union numbers first_number;
first_number.i = 5;
first_number.f = 3.9;
printf("%i %'.2f\n", first_number.i, first_number.f);
为什么在使用first_number.i
进行编译后,没有警告gcc -Wall file.c
被覆盖,而first_number.i
的最终结果是从哪里来的呢?
至少,覆盖工会成员的一般目的是什么,而不是声明更多的工会变量来避免这种行为,这会更好吗?
答案 0 :(得分:2)
这就是C工会的工作方式。如果要使用非重叠字段,请使用结构。存储浮点值后的.i
成员的值是解释为int的位模式。
答案 1 :(得分:1)
当您在不同时间需要不同的字段时,它用于节省空间(内存)。
没有多余的空间来记录联合的最后一个字段。因此,当程序运行时,没有办法自动检测到读取“错误”字段。程序员必须自己这样做。而且在大多数情况下,编译器也无法检测到此类读取。
但是即使在 可以检测到的情况下,GCC也不会对此发出警告。为什么?
这是因为C程序员有时要做想要将内存中的类型A重新解释为类型B。我们很奇怪。
GCC明确记录了可以重新解释类型的文档-如果使用联合。与其他主要编译器一样。对于正式的C标准是否都设法正确定义了此规则,有些困惑。但是每个人都同意规则在实践中。
https://blog.regehr.org/archives/1307#comment-18418
https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
您可能会认为可以使用指针强制转换而不是联合。你会错的。该行为由标准“未定义”。编译器可以将任何可能发生的代码路径都视为不可能,并忽略它。然后任何事情都可能发生。此过程称为“优化”。
https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
建议用户不要太用心考虑如果您开始弄乱指向工会不同字段的指针,并确保他们永远不要这样做。 https://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified#comment61928962_11640381
C ++用户应改用reinterpret_cast<>
。还据称标准C ++不支持使用union
重新解释类型。