这是我的代码。它适用于C,但它的行为类似于C ++中的结构。
#include<iostream>
using namespace std;
int main()
{
union myunion
{
int B;
double PI;
};
union myunion numbers;
numbers.PI = 3.14;
numbers.B = 12;
/* now storage of PI should be over-written */
cout<<numbers.PI<<endl;
cout<<numbers.B<<endl;
/* Output is 3.14 */
/* 12 */
/* Why it is behaving like Structures ? */
return 0;
}
答案 0 :(得分:6)
评论者提到了Cppreference on union
states:
从未最近编写的联盟成员中读取未定义的行为。
这就是为什么你的程序表现如此:它的未定义行为。它可以显示之前的值,或崩溃,或之间的任何内容。
numbers.PI = 3.14;
numbers.B = 12;
cout<<numbers.PI<<endl; // undefined behaviour
答案 1 :(得分:2)
其他人向你解释了为什么这是不明确的行为 - 以及为什么永远不会这样做 - 但如果你仍然对这里发生的事情感到好奇:请继续阅读。
使用正确的编译器,在正确的平台上,在月亮的正确阶段,会发生以下情况。
sizeof(double)
== 8 numbers.PI
设置为3.14将内存中的8个字节设置为1f 85 eb 51 b8 1e 09 40
并在观察窗口中显示numbers {B=1374389535 PI=3.1400000000000001}
sizeof(int)
== 4 numbers.B
设置为12时,仅更改该内存的前四个字节。 numbers
现在存储为0c 00 00 00 b8 1e 09 40
(0c000000在我的英特尔处理器上为12),而b81e09f0则是PI留下的内容。numbers
现在在观察窗口中显示为numbers {B=12 PI=3.1399993896484428}
因此,numbers.PI
已被修改!它是3.1400000000000001,现在是3.1399993896484428。但是,当您将其流式传输到cout
时,其新值将四舍五入为3.14以用于显示目的,隐藏其值已更改的事实。
但请记住 - 访问除最近设置的联盟之外的任何联盟成员仍未定义的行为。