C++ union 表示数据内存与 C 标量变量类型

标签 c++ c floating-point integer unions

今天我有一个奇怪的问题。

代码(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;
}

问题

  1. 正如我们所知,C++ union 可以容纳不止一种类型的数据元素,但一次只能容纳一种类型。所以基本上 name oblong 只会保留 32 位内存的一部分(因为 union 中最大的类型是 32 位,int 和 float),这部分可以保存整数或 float 。

  2. 所以我只是将值 27.881 分配给 oblong.num2(如您在上面的代码中所见)。但出于好奇,我使用指向相同内存位置的 oblong.num 访问内存。

  3. 正如预期的那样,它给了我一个不是 27 的值,因为 float 和整数在内存中的表示方式不同,这就是为什么当我使用 oblong.num 访问内存时部分它将内存值的那部分视为整数并使用整数表示方式对其进行解释。

  4. 我知道这种现象在 C 中也会发生,这就是为什么我用一个值初始化一个 float 类型的变量,然后使用 %d 读取它。所以我只是尝试一下通过使用您在上面看到的相同值 27.881。但是当我运行它时,发生了一些奇怪的事情,那就是我在 C 中得到的值与 C++ 不同。

  5. 为什么会这样?据我所知,我最后从两个代码中得到的两个值不是垃圾值,但为什么我得到不同的值呢?我还使用 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/

相关文章:

c++ - 如何监控一个ZeroMQ服务器是否存在?

c - 如何将 Windows 客户端设置为基于 Web 的 dll

ios - 增加 float 一定时间段?

c# - 未初始化的浮点变量,重新定义不确定的行为

c++ - 通过引用 char 2 维调用字符串不起作用

c++ - 批评我的堆调试器

c - 使用 Visual Studio 2010,如何向 Visual C++ Win32 控制台应用程序提供输入?

在 Borland C 中创建未修饰的函数

c - 使用最接近的浮点运算

c++ - QString 到 char* 的转换