c语言中的Union每次存储一个数据

union in c stores one data at a time

本文关键字:数据 一个 存储 语言 Union      更新时间:2023-10-16

如果在内存中分配的联合的大小等于最大的数据类型成员字节,那么谁能告诉我编译器是如何存储和获取两个数据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"的回答

您可以将id存储到您的联合中,而不是同时存储这两个。语句

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
相关文章: