类型双关——编译器如何决定使用什么类型

Type punning - how does the compiler decide what type to use?

本文关键字:类型 什么 决定 何决定 编译器      更新时间:2023-10-16

我在这里读到了这个关于决定endianness的问题,第一个答案让我有些困惑。

用于决定大端序的代码如下:

int is_big_endian(void)
{
    union {
        uint32_t i;
        char c[4];
    } bint = {0x01020304};
    return bint.c[0] == 1; 
} 

我的问题是这里的编译器如何决定使用什么类型的十六进制数字数组?因为从技术上讲,它同样适用于uint32_tchar[4]

为什么不将其存储在char[4]中并跳过union呢?

union有什么我看不到的优点吗?我知道这叫做类型双关,但我看不出它在这里的优势。

我的问题是,这里的编译器如何决定对十六进制数字数组使用什么类型?

与数组和聚合类一样,第一个初始化程序初始化第一个成员;在这种情况下为CCD_ 6。(当然,与这些不同的是,拥有一个以上的初始化程序是没有意义的)。

为什么不直接将其存储在char[4]中并跳过并集呢?这里的工会有什么我看不到的优势吗?

这样做的目的是初始化4字节整数,然后使用char数组检查各个字节以确定内存顺序。如果最高有效字节(0x01)存储在第一个字节中,则系统为"big-endian";否则它就是"小endian"(或者可能是一些奇怪的东西)。

最初的C标准只允许为并集的第一个元素赋值。这意味着:0x1020304被分配给"i",而不是"c"。

最新的C标准允许分配给任何成员,如下所示:

union { ... } bint = { .c = {1,2,3,4} };
union { ... } bint2 = { .i = 0x1020304 };

但是,如前所述,如果没有给出名称,则将值分配给"i"。

因为您想0x01020304存储为无符号32位整数uint32_t i,然后读取第一个字节char c[0]