c语言中的Union每次存储一个数据
union in c stores one data at a time
如果在内存中分配的联合的大小等于最大的数据类型成员字节,那么谁能告诉我编译器是如何存储和获取两个数据double d和int i(总共8+4字节)(我的机器上的double是8字节)
#include<stdio.h>
union test {
int i;
double d;
};
int main()
{
union test obj;
obj.d=15.5;
obj.i=200;
printf("nValue stored in d is %f",obj.d);
printf("nValue stored in i is %d",obj.i);
printf("n size of obj is %d ",sizeof(obj));
}
**Output is : Value stored in d is 15.500000
Value stored in i is 200
size of obj is 8**
它能存储这两者的方式是"纯粹的运气"。我将假设您的计算机架构使用IEEE 754浮点数,并尝试解释您所看到的内容。您的联合确实只使用8个字节,但15.5在十六进制中看起来像这样:402F000000000000
。正如您所看到的,较低的四个字节完全为零。现在让我们将最小的4个字节设置为整数200,看看8个字节的值会发生什么变化。得到402F0000000000C8
。现在假设你现在读取所有8个字节作为双精度,在IEEE754中你得到15.500000000000355
,当打印时将四舍五入到15.5,使它看起来可以同时存储双精度和整型。
像这样访问联合的两个成员在c++中至少在c++ 11之前是未定义的行为(尽管它在我所知道的所有平台上都以逻辑方式运行),所以这只是你观察到的行为的一种可能的解释。在C语言中,这似乎是完全合法的。
看起来你可以在重叠的内存中存储两个数字的原因是你选择的小值的表示方式的安排。
如果您尝试需要存储更多信息的值,例如:
obj.d=100000000000000;
obj.i=0xffffffff;
您将看到打印double
值的输出中的差异:
Value stored in d is 100000059097087.984375
我认为它并没有像你想象的那样工作。如果您在测试中添加更多内容:
#include<stdio.h>
union test {
int i;
double d;
};
int main()
{
union test obj;
obj.d=15.5;
obj.i=200;
printf("nValue stored in d is %f",obj.d);
printf("nValue stored in i is %d",obj.i);
printf("n size of obj is %d ",sizeof(obj));
obj.d=17.5;
printf("nValue stored in d is %f",obj.d);
printf("nValue stored in i is %d",obj.i);
printf("n size of obj is %d ",sizeof(obj));
obj.i=300;
printf("nValue stored in d is %f",obj.d);
printf("nValue stored in i is %d",obj.i);
printf("n size of obj is %d ",sizeof(obj));
}
输出是:
$ ./main
Value stored in d is 15.500000
Value stored in i is 200
size of obj is 8
Value stored in d is 17.500000
Value stored in i is 0
size of obj is 8
Value stored in d is 17.500000
Value stored in i is 300
size of obj is 8
注意i的值在中间是0 !这是因为它(部分?)被覆盖了。
如果我理解正确的话,它在那里是未定义的行为,你看到的确切值将取决于你编译它的架构,编译器对这个结构使用的对齐方式等等。
编辑:我想我现在理解了最初的问题——它是关于,为什么有可能恢复第一个存储值,对吧?为什么我看到的不是乱码,而是200。
我的猜测是,它可能取决于一些实现细节的浮点的东西?如果是像17.5这样的"简单"双精度类型,可能双精度类型碰巧没有覆盖"int"的位。不完全确定。编辑:参见"imreal"的回答
您可以将i
或d
存储到您的联合中,而不是同时存储这两个。语句
obj.i=200;
覆盖为联合分配的内存中存储的值。现在使用%f
指示符访问obj.d
将调用未定义的行为,这是因为存储在obj
中的值是int
。
写入obj.i
后,从obj.d
读取是未定义的行为,就C标准而言,任何事情都可能发生。
在这种特殊情况下,您可能不会看到发生任何事情,因为浮点数是在内存中布局的。你正在改变尾数的一些最低有效位,创造了一个在前6个十进制数字中看不到的变化。添加更多数字:
printf("nValue stored in d is %.17f",obj.d);
,你会得到:
Value stored in d is 15.50000000000035705
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- 矢量如何将数据复制到另一个矢量?
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 我的程序有一个保存配置文件的GUI,如何双击此配置文件以直接加载带有配置数据的GUI?
- 在学习数据结构之前对STL有一个了解是好的吗?
- 如何在 c++ 中比较 2 个链表并将匹配的数据放入另一个链表中
- 如何在 Gnuplot 中分别绘制 2 个文件数据?我有一个文件"sin.txt",另一个文件"cos.txt",我想将它们分别绘制在一个图表上
- 将父类的子类的数据复制到具有相同父类的另一个类
- 使用完数据结构后清空数据结构是一个好习惯吗?
- 在CRC-16 CCITT中将数据从二进制解码为文本,我应该输入一个码字,使用CRC生成器进行编码
- 如何将数据从一个结构链接到另一个结构
- 如何通过另一个对象中的命令正确地从一个对象返回数据
- 大家好,当一个类有一个向量作为它的数据成员时,为什么它的大小总是24?
- 如何在C++中将用户数据从一个 Lua 块传递到另一个块
- 将矢量数据从一个类复制到另一个类
- 如果我们不创建一个新节点并使用指针插入数据并建立链接(在链表中)怎么办?
- 我想知道我是否可以将一个类分配给特定的成员数据并创建该类的实例
- 在C++中创建一个简单的数据包路由器,如何跟踪"客户端"?
- 将一个阵列中的数据存储到另外两个阵列中不起作用