[英]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。 谁能解释第一种情况?
读取不是最后一个写入的工会成员的行为实际上是未定义的。
如果联合中的项目与布局兼容 (如标准中所定义),则可以执行此操作,但int
和char
情况并非如此(更正确的是,如果这两种类型具有相似的位宽,但通常不是这种情况)。
从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.