工会不能正常工作

时间:2017-01-11 05:47:31

标签: c++ data-structures structure storage unions

这是我的代码。它适用于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;
}

2 个答案:

答案 0 :(得分:6)

评论者提到了Cppreference on union states

  

从未最近编写的联盟成员中读取未定义的行为。

这就是为什么你的程序表现如此:它的未定义行为。它可以显示之前的值,或崩溃,或之间的任何内容。

numbers.PI = 3.14;
numbers.B = 12; 

cout<<numbers.PI<<endl; // undefined behaviour

答案 1 :(得分:2)

其他人向你解释了为什么这是不明确的行为 - 以及为什么永远不会这样做 - 但如果你仍然对这里发生的事情感到好奇:请继续阅读。

使用正确的编译器,在正确的平台上,在月亮的正确阶段,会发生以下情况。

  1. sizeof(double) == 8
  2. numbers.PI设置为3.14将内存中的8个字节设置为1f 85 eb 51 b8 1e 09 40并在观察窗口中显示numbers {B=1374389535 PI=3.1400000000000001}
  3. sizeof(int) == 4
  4. 因此 - 当您将numbers.B设置为12时,仅更改该内存的前四个字节numbers现在存储为0c 00 00 00 b8 1e 09 40(0c000000在我的英特尔处理器上为12),而b81e09f0则是PI留下的内容。
  5. 碰巧的是,英特尔,IEEE和编译器工会的打包订单导致了12个只丢弃PI尾数中最不重要的部分(不会打扰它的指数)。
  6. numbers现在在观察窗口中显示为numbers {B=12 PI=3.1399993896484428}
  7. 因此,numbers.PI 已被修改!它是3.1400000000000001,现在是3.1399993896484428。但是,当您将其流式传输到cout时,其新值将四舍五入为3.14以用于显示目的,隐藏其值已更改的事实。

    但请记住 - 访问除最近设置的联盟之外的任何联盟成员未定义的行为。