工会工作不正常
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
其他人已经向您解释了为什么这是未定义的行为——以及为什么永远不要这样做——但如果您仍然对这里发生的事情感到好奇:请继续阅读。
使用正确的编译器,在正确的平台上,在正确的月相期间,会发生以下情况。
sizeof(double)
== 8
- 设置
numbers.PI
为3.14,将内存中的8个字节设置为1f 85 eb 51 b8 1e 09 40
,在手表中显示numbers {B=1374389535 PI=3.1400000000000001}
window
sizeof(int)
== 4
- 所以 - 当您将
numbers.B
设置为 12 时,只有该内存的前四个字节 会被更改。 numbers
现在存储为 0c 00 00 00 b8 1e 09 40
(0c000000 在我的英特尔处理器上是 12),b81e09f0 是 PI 留下的。
- 碰巧的是,英特尔、IEEE 和编译器联合打包顺序导致 12 位垃圾仅破坏 PI 尾数的最低有效位(不影响其指数)。
numbers
现在在手表 window 中显示为 numbers {B=12 PI=3.1399993896484428}
所以,numbers.PI
已经修改!它是 3.1400000000000001,现在是 3.1399993896484428。但是,当您将它流式传输到 cout
时,它的新值会四舍五入为 3.14 以进行显示,隐藏其值已更改的事实。
但请记住 - 访问除最近集合以外的任何联合成员都是仍然未定义的行为。
这是我的代码。它在 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
其他人已经向您解释了为什么这是未定义的行为——以及为什么永远不要这样做——但如果您仍然对这里发生的事情感到好奇:请继续阅读。
使用正确的编译器,在正确的平台上,在正确的月相期间,会发生以下情况。
sizeof(double)
== 8- 设置
numbers.PI
为3.14,将内存中的8个字节设置为1f 85 eb 51 b8 1e 09 40
,在手表中显示numbers {B=1374389535 PI=3.1400000000000001}
window sizeof(int)
== 4- 所以 - 当您将
numbers.B
设置为 12 时,只有该内存的前四个字节 会被更改。numbers
现在存储为0c 00 00 00 b8 1e 09 40
(0c000000 在我的英特尔处理器上是 12),b81e09f0 是 PI 留下的。 - 碰巧的是,英特尔、IEEE 和编译器联合打包顺序导致 12 位垃圾仅破坏 PI 尾数的最低有效位(不影响其指数)。
numbers
现在在手表 window 中显示为numbers {B=12 PI=3.1399993896484428}
所以,numbers.PI
已经修改!它是 3.1400000000000001,现在是 3.1399993896484428。但是,当您将它流式传输到 cout
时,它的新值会四舍五入为 3.14 以进行显示,隐藏其值已更改的事实。
但请记住 - 访问除最近集合以外的任何联合成员都是仍然未定义的行为。