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

car*_*995 6 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;
}
Run Code Online (Sandbox Code Playgroud)

守则(C)

#include <stdio.h>

int main(void)
{
    float num = 27.881;

    printf("%d\n" , num);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题

  1. 众所周知,C++联合可以包含多种类型的数据元素,但一次只能包含一种类型.所以基本上name oblong只会保留一部分32位的内存(因为联合中最大的类型是32位,int和float),这部分可以保存整数或浮点数.

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

  3. 正如预期的那样,它给了我一个不是27的值,因为浮点数和整数在内存中表示的方式是不同的,这就是为什么当我oblong.num用来访问内存部分时它会把那部分内存值当作整数来解释它整数表示方式.

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

  5. 为什么会这样?据我所知,我从两个代码到底得到的两个值不是垃圾值,但为什么我得到不同的值?我还使用sizeof来验证C和C++整数和浮点大小,两者都是32位.因此,内存大小不会导致这种情况发生,那么是什么促使这些值的差异?

Mys*_*ial 9

首先,具有错误的printf()格式字符串是未定义的行为.现在说,这是你的案件实际发生的事情:

在vararg函数中,例如printf(),小于int被提升的整数int和浮动小于double被提升的double.

结果是,在27.881传入时,您将被转换为8字节的双精度数printf().因此,二进制表示不再与a相同float.

格式字符串%d需要一个4字节的整数.因此,实际上,您将打印双精度表示的低4字节27.881.(假设小端)

*实际上(假设是严格的FP),你看到27.881它被转换为后面的底部4个字节float,然后被提升为double.