今天我有一个奇怪的问题。
代码(C++)
#include <iostream>
union name
{
int num;
float num2;
}oblong;
int main(void)
{
oblong.num2 = 27.881;
std::cout << oblong.num << std::endl;
return 0;
}
代码(C)
#include <stdio.h>
int main(void)
{
float num = 27.881;
printf("%d\n" , num);
return 0;
}
问题
正如我们所知,C++ union 可以容纳不止一种类型的数据元素,但一次只能容纳一种类型。所以基本上
name oblong
只会保留 32 位内存的一部分(因为 union 中最大的类型是 32 位,int 和 float),这部分可以保存整数或 float 。所以我只是将值 27.881 分配给
oblong.num2
(如您在上面的代码中所见)。但出于好奇,我使用指向相同内存位置的oblong.num
访问内存。正如预期的那样,它给了我一个不是 27 的值,因为 float 和整数在内存中的表示方式不同,这就是为什么当我使用
oblong.num
访问内存时部分它将内存值的那部分视为整数并使用整数表示方式对其进行解释。我知道这种现象在 C 中也会发生,这就是为什么我用一个值初始化一个 float 类型的变量,然后使用
%d
读取它。所以我只是尝试一下通过使用您在上面看到的相同值27.881
。但是当我运行它时,发生了一些奇怪的事情,那就是我在 C 中得到的值与 C++ 不同。为什么会这样?据我所知,我最后从两个代码中得到的两个值不是垃圾值,但为什么我得到不同的值呢?我还使用 sizeof 来验证 C 和 C++ 整数和浮点大小,它们都是 32 位的。所以内存大小不是导致这种情况发生的原因,那么是什么导致了这种值差异?
最佳答案
首先,具有错误的printf()
格式字符串是未定义的行为。话虽如此,这就是您的情况实际发生的情况:
在 printf()
等可变参数函数中,小于 int
的整数被提升为 int
并且小于 double< 的 float
被提升为 double
。
结果是您的 27.881
在传递到 printf()
时被转换为 8 字节 double 。因此,二进制表示不再与 float
相同。
格式字符串 %d
需要一个 4 字节整数。所以实际上,您将打印 27.881
的 double 表示的低 4 字节。 (假设是小端)
*实际上(假设是严格的 FP),在将 27.881
转换为 float
,然后提升为 之后,您会看到它的底部 4 个字节双
。
关于C++ union 表示数据内存与 C 标量变量类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8103403/