工会工作不正常

Unions not working properly

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

评论者提到,Cppreference on union states:

it's undefined behavior to read from the member of the union that wasn't most recently written.

这就是您的程序如此行为的原因:它是未定义的行为。它可以显示以前的值、崩溃或介于两者之间的任何值。

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

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

其他人已经向您解释了为什么这是未定义的行为——以及为什么永远不要这样做——但如果您仍然对这里发生的事情感到好奇:请继续阅读。

使用正确的编译器,在正确的平台上,在正确的月相期间,会发生以下情况。

  1. sizeof(double) == 8
  2. 设置numbers.PI为3.14,将内存中的8个字节设置为1f 85 eb 51 b8 1e 09 40,在手表中显示numbers {B=1374389535 PI=3.1400000000000001}window
  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 现在在手表 window 中显示为 numbers {B=12 PI=3.1399993896484428}

所以,numbers.PI 已经修改!它是 3.1400000000000001,现在是 3.1399993896484428。但是,当您将它流式传输到 cout 时,它的新值会四舍五入为 3.14 以进行显示,隐藏其值已更改的事实。

但请记住 - 访问除最近集合以外的任何联合成员都是仍然未定义的行为。