以正确的方式确定C中机器体系结构的字节顺序

Determining endianness of machine architecture in C the correct way

我刚刚编写了以下函数来确定机器体系结构的字节顺序(虽然是为基于 ARM Cortex-M7 体系结构的 MCU 编写的,但希望功能使代码可移植):

uint8_t is_little_endian()
{
   static const union test {
      uint32_t num;
      uint8_t  bytes[sizeof(uint32_t)];
   } p = {.num =  1U };              

   return (p.bytes[0] == 1U); 
}

我只是想知道如果我在这里使用 unsigned intchar 而不是上面代码中的 uint32_tuint8_t 是否会出现任何错误结果?如果是,为什么?

你可以简单地return ntohs(12345) != 12345

为了回答您的直接问题,unsignedchar 也可以正常工作 if CHAR_BIT < 16。这是因为 C 标准要求 unsigned 至少有 16 个值位,并且每种类型的存储大小必须是 char 的倍数(一个字节)。因此,只要您的 char 少于 16 位,unsigned 就必须至少包含 2 个字节,字节序检查将以这种方式进行。

使用 char 实际上有一个好处,它允许为任何其他类型起别名。所以我建议这样:

#include <limits.h>
#if CHAR_BIT > 15
#error exotic platform
#endif

int is_little_endian(void)
{
    unsigned x = 1U;
    unsigned char *r = (unsigned char *)&x;
    return !!*r;
}

我在这里使用 unsigned char 只是为了确定。

请注意,这是假设没有 exotic 字节顺序(如 "middle-endian")。另外,我个人认为这样的代码在程序中是 space 的浪费,如果你真的需要字节顺序信息,最好让你的构建系统为你的目标确定它并且只是 #define 它(例如在 config.h 文件中)。

I was just wanting to know if there will be false results if I use unsigned int and char here instead of uint32_t and uint8_t? If yes, why?

是的,可能。

提到的类型(unsigned intchar)是 实现定义的。它可能取决于编译器、机器、编译器选项等。如果您查看 stdint.h. This is part of the standard library 中声明的类型,那么预计(尽管技术上不能保证)在任何地方都可用。此处声明的类型包括 int8_tuint8_tint16_tuint16_tint32_tuint32_tint64_tuint64_t.