C++ 联合用法和混乱代码
我有一些关于union用法的代码,如下所示:C++ 联合用法和混乱代码,c++,gcc,unions,C++,Gcc,Unions,我有一些关于union用法的代码,如下所示: int main(){ typedef union{int a;char b[10];float c;}Union; Union x,y = {100}; printf("Union x :%d| |%s| |%f \n",x.a,x.b,x.c ); printf("Union y :%d| |%s| |%f \n\n",y.a,y.b,y.c); x.a = 50; printf("Union x :
int main(){
typedef union{int a;char b[10];float c;}Union;
Union x,y = {100};
printf("Union x :%d| |%s| |%f \n",x.a,x.b,x.c );
printf("Union y :%d| |%s| |%f \n\n",y.a,y.b,y.c);
x.a = 50;
printf("Union x :%d| |%s| |%f \n",x.a,x.b,x.c );
printf("Union y :%d| |%s| |%f \n\n",y.a,y.b,y.c);
strcpy(x.b,"hello");
printf("Union x :%d| |%s| |%f \n",x.a,x.b,x.c );
printf("Union y :%d| |%s| |%f \n\n",y.a,y.b,y.c);
x.c = 21.50;
printf("Union x :%d| |%s| |%f \n",x.a,x.b,x.c );
printf("Union y :%d| |%s| |%f \n\n",y.a,y.b,y.c);
return 0;
}
编译并执行上述代码后,得到如下结果:
Union x :0| || |0.000000
Union y :100| |d| |0.000000
Union x :50| |2| |0.000000
Union y :100| |d| |0.000000
Union x :1819043176| |hello| |1143141483620823940762435584.000000
Union y :100| |d| |0.000000
Union x :1101791232| || |21.500000
Union y :100| |d| |0.000000
我不知道为什么y.b被初始化为“d”?为什么x.a和x.c的值在之后会发生变化?为什么strcpy(x.b,“hello”)不起作用?如果您看到一个,您将看到值100
与字符'd'
相同
你必须记住,工会的所有成员都有相同的记忆。这意味着,如果您设置一个联盟的一个成员,那么所有成员都会发生变化,而且并不总是发生可以理解的变化。因此,向一个成员写入而从另一个成员读取是未定义的行为
而且strcpy(x.b,“hello”)
确实有效,因为您可以看到x
联合的所有成员在您这样做后都发生了变化。如果您看到一个,您将看到值100
与字符'd'
相同
你必须记住,工会的所有成员都有相同的记忆。这意味着,如果您设置一个联盟的一个成员,那么所有成员都会发生变化,而且并不总是发生可以理解的变化。因此,向一个成员写入而从另一个成员读取是未定义的行为
而且strcpy(x.b,“hello”)
确实有效,因为您可以看到x
联盟的所有成员在您这样做之后都发生了变化。您的代码具有UB(未定义的行为);分配给联合的一个成员,然后检查另一个成员是非法的(POD结构具有相同初始成员的特殊情况除外)
在将代码分配到x.a
之前,读取未初始化的值(例如x
的任何字段)也是非法的;分配给联合的一个成员,然后检查另一个成员是非法的(POD结构具有相同初始成员的特殊情况除外)
在分配到
x.a
之前,读取未初始化的值(例如x
的任何字段)也是非法的。我认为当你说int a时,你分配了sizeof(int),通常是32位。
但是当你说char[10]时,你是在分配10*sizeof(char)字节!!(10*4位)
这两者不能相互转换。我认为当你说int a时,你分配了sizeof(int),通常是32位。 但是当你说char[10]时,你是在分配10*sizeof(char)字节!!(10*4位) 这两种类型不能相互转换。严格按照标准类型双关语,在狭窄的情况下除外,但实际上许多编译器都支持它,例如,-fstrict别名部分说: 从不同的工会成员那里阅读而不是最近写信给的工会成员(称为“类型双关语”)的做法很常见。即使使用-fstrict别名,也允许使用类型punning,前提是通过联合类型访问内存 如果你打算大量使用类型双关语,我建议你阅读
y.b
具有值b
,因为union的所有元素都共享内存,并且您使用100
初始化y
,在ASCII中为b
。这也是为什么当您修改其中一个字段(包括strcpy
的情况)时,x
的其他字段会发生更改的原因,并且根据您的编译器,这可能是未定义的或定义良好的(在gcc的情况下,它是已定义的)
出于完整性考虑,C++草稿标准部分<代码> 9.5 /代码>第1段(强调矿山):
在联合中,最多一个非静态数据成员可以在任何时间处于活动状态,即,最多一个非静态数据成员的值可以在任何时间存储在联合中。[注:为简化联合体的使用,我们提供了一项特殊保证:如果一个标准布局联合体包含多个共享公共初始序列的标准布局结构(9.2),并且如果此标准布局联合类型的对象包含一个标准布局结构,则允许检查任何标准布局结构成员的公共初始序列;参见9.2.-结束注释]联合的大小足以包含其最大的非静态数据成员。每个非静态数据成员都被分配,就像它是结构的唯一成员一样 严格按照标准的类型双关,在狭窄的环境中expect是,但实际上许多编译器都支持它,例如,-fstrict aliasing部分中说: 从不同的工会成员那里阅读而不是最近写信给的工会成员(称为“类型双关语”)的做法很常见。即使使用-fstrict别名,也允许使用类型punning,前提是通过联合类型访问内存 如果你打算大量使用类型双关语,我建议你阅读y.b
具有值b
,因为union的所有元素都共享内存,并且您使用100
初始化y
,在ASCII中为b
。这也是为什么当您修改其中一个字段(包括strcpy
的情况)时,x
的其他字段会发生更改的原因,并且根据您的编译器,这可能是未定义的或定义良好的(在gcc的情况下,它是已定义的)
出于完整性考虑,C++草稿标准部分<代码> 9.5 /代码>第1段(强调矿山):
在联合中,最多一个非静态数据成员可以在任何时间处于活动状态,即,最多一个非静态数据成员的值可以在任何时间存储在联合中。[注:为简化联合体的使用,我们提供了一项特殊保证:如果一个标准布局联合体包含多个共享公共初始序列的标准布局结构(9.2),并且如果此标准布局联合类型的对象包含一个标准布局结构,则允许检查任何标准布局结构成员的公共初始序列