输入惩罚 - 编译器如何决定使用哪种类型?

时间:2013-08-22 14:11:43

标签: c++ unions type-punning

我正在阅读this question here about deciding 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的某些优点我看不到吗?我知道这被称为打字,但我没有看到它的优势。

3 个答案:

答案 0 :(得分:6)

  

我的问题是这里的编译器如何决定用于该十六进制数字数组的类型?

与数组和聚合类一样,第一个初始化器初始化第一个成员;在这种情况下i。 (当然,与那些东西不同,拥有多个初始化器是没有意义的。)

  

为什么不将它存储在char [4]中并跳过联合?在这里,我看不到一个联盟的优势吗?

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

答案 1 :(得分:2)

原始C标准只允许为联合的第一个元素赋值。这意味着:0x1020304被分配给“i”,而不是“c”。

最新的C标准允许分配给这样的任何成员:

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

然而 - 如上所述 - 如果没有给出名字,则将该值分配给“i”。

答案 2 :(得分:0)

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