在cpp中使用union的未定义bhaviour?

时间:2013-08-28 06:24:44

标签: c++ unions

我正在使用c ++进行联合, 以下是代码段:

#include<iostream>
using namespace std;

typedef union myunion
{
  double PI;
  int B;
}MYUNION;

int main()
{
  MYUNION numbers;
  numbers.PI = 3;
  numbers.B = 50;
  cout <<" numbers.PI :" << numbers.PI << endl;
  if(numbers.PI == 3.0)
  {
      cout <<"True";
    if(numbers.B == 50)
    {
      cout <<" numbers.PI :" << numbers.PI << endl;
       cout <<" numbers.B :" << numbers.B << endl;
    }
  }

  return 0;
}

输出是:

 numbers.PI :3

数字的偶数值.PI已设置为3,首先“if”条件为false。 这种行为的原因是什么?

3 个答案:

答案 0 :(得分:5)

原因是没有理由。

您的代码调用未定义的行为,因为您正在设置union的B成员:

numbers.B = 50;

但在设置之后,您立即宣读其他成员 PI

cout <<" numbers.PI :" << numbers.PI << endl;

也许你让工会和结构混淆 - 除非浮点数3和整数50在您的架构上具有相同的位表示(这是非常的不太可能),只有当您使用struct时,您对程序的期望才会合理。

union成员驻留在内存中的同一位置 - 设置一个也会覆盖另一个。对于struct,每个成员都存储在不同的内存位置,这不是真的。 )

答案 1 :(得分:2)

请记住,联盟的所有成员共享相同的内存。当您分配到B时,您也会更改PI的值。

为了安全起见,您应该只从“写入”的最后一个字段“读取”。

在我看来,你想要的是一个结构。

答案 2 :(得分:0)

你正在获得未定义的行为,但这是幕后发生的事情:

你正在使用sizeof(int)&lt;的小端机器。 sizeof(double),例如x86。几乎可以肯定,该机器使用IEEE 754格式的浮点/双(这些天几乎所有机器都这样)。

当您写入B字段时,它会覆盖PI中双精度的低位。所以 当您最初在PI中存储3.0时,会将其设置为0x4008000000000000。然后,当您将B中的50存储为PI更改为0x4008000000000032时,恰好是3.00000000000002220446049250313080847263336181640625。因此,它不等于3.0,但是当您使用默认精度打印时,它会将其舍入为3.0