繁体   English   中英

C ++ Union成员未初始化

[英]C++ Union member not initialized

当我发现一些奇怪的东西时,我才刚刚开始寻找工会

如果我运行此程序

    #include <iostream>
    using namespace std;
    union myun{
    public:
    int x;
    char c;
    };

    int main()
    {
     myun y;
     //y.x=65;
      y.c='B';
     cout<<y.x;
    }

输出是一些垃圾值,如果更改yc的值,则不会改变。

    #include <iostream>
    using namespace std;
    union myun{
    public:
    int x;
    char c;

    };
     int main()
     {
      myun y;
      y.x=65;
      y.c='B';
      cout<<y.x;
     }

预期输出为66,因为yc ='B'用其ASCII值(66)替换了65。 谁能解释第一种情况?

读取不是最后一个写入的工会成员的行为实际上是未定义的。

如果联合中的项目与布局兼容 (如标准中所定义),则可以执行此操作,但intchar情况并非如此(更正确的是,如果这两种类型具有相似的位宽,但通常不是这种情况)。

从C ++ 03标准(现在已由C ++ 11取代,但仍然相关):

在联合中,最多可以在任何时间激活一个数据成员,即,最多可以在任何时间将一个数据成员的值存储在一个联合中。

我想如果您想进行这种叠加活动,则可能需要研究reinterpret_cast


根据第一个幕后的实际情况,数字输出的十六进制值:

-1218142398 (signed) -> 3076824898 (unsigned) -> B7649F42 (hex)
                                                       ==
                                                       ^^
                                                       ||
                                       0x42 is 'B' ----++

应该提供一个线索。 yc='B'仅设置该结构的单个字节 ,而其余​​三个字节(在我的情况下)则不确定。

通过在该点之前放置yx=65行,它将设置所有四个字节,并将这三个备用字节设置为零。 因此,当您在以下分配中设置单个字节时,它们保持为零。

好吧,当您对第二种情况有所了解时,您就可以解释第一种情况。

初始化字符部分只会修改提供int的数据类型中的一个字节。 假设int为32位,则意味着3个字节仍未初始化。

这是您的联合的内存使用情况:

              byte
           0  1  2  3
         +------------
myun::x  | X  X  X  X
myun::c  | X  -  -  -

设置x ,设置整数,以便初始化所有剩余字节。 设置c ,仅修改单个字节。

  y.c='B';
 cout<<y.x;

这具有不确定的行为。 在任何给定时间,工会仅包含其成员之一。 如果int成员实际上包含char成员,则不能尝试读取它。 由于未定义此行为,因此允许编译器使用代码执行所需的操作。

因为sizeof(int) != sizeof(char)

也就是说,一个整数和一个字符占用不同的内存量(在当今的普通计算机中,int是4个字节,char是1个字节)。 工会的规模仅与其最大的会员一样大。 因此,当您设置字符时,您只设置了1个字节的内存-其他3个字节只是随机垃圾。

首先设置工会的最大成员,或执行以下操作:

memset(&y, 0, sizeof(y));

用零填充整个联合

在联合中,分配的内存等于最大成员的大小,在您的情况下为int,即对于16位编译器为2个字节。 所有成员都使用相同的存储空间来存储其数据,因此,实际上一次只能存储一种类型的成员。

当您将值'B'分配给char成员时,它将66存储在其1字节的存储空间中。 然后,您尝试输出int成员的值,但是该成员试图通过从内存的2个字节中读取值来计算值,因此得到了一个垃圾值。

声明时,POD类型的局部变量(更具体地说是堆栈中的变量,即具有“自动”的存储类)不会初始化为任何东西,因此3个字节(在64位系统上为7个字节)不会受到影响您对yc的分配将包含随机垃圾。

还要注意,受yc赋值影响的特定字节取决于CPU的字节顺序,因此即使在将yx赋值给yc之前初始化yx ,此代码在不同的系统上也会有不同的行为。

变量y是联合类型,并且y的长度为四个字节。 例如,y的内存布局是这样的:

---------------------------------
| byte1 | byte2 | byte3 | byte4 |
---------------------------------

1)在第一个程序中,句子yc='B'; 只需设置字节1,但字节2,字节3,字节4是堆栈中的随机值。

2)在第二个程序中,句子yx = 65; 将byte1设置为65,则byte2,byte3,byte4为零。 然后,句子yc='B'; 将byte1设置为ASCII整数值“ B”,因此输出为66。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM