以正确的方式确定C语言中机器架构的字节序

时间:2018-08-01 12:01:47

标签: c endianness

我刚刚编写了以下函数来确定计算机体系结构的字节序(尽管是为基于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会不会有错误的结果?如果是,为什么?

3 个答案:

答案 0 :(得分:4)

要回答您的直接问题,如果 unsigned也可以使用charCHAR_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”)。另外,我个人认为,这样的代码浪费了程序空间,如果您确实需要字节序信息,则最好让您的构建系统为目标确定它,然后#define(例如,在{{ 1}}文件。

答案 1 :(得分:1)

  

我只是想知道如果我使用,是否会有错误的结果   这里是unsigned intchar而不是uint32_tuint8_t?如果   是的,为什么?

是的,可能。

提到的类型(unsigned intchar)是实现定义的。它可能取决于编译器,计算机,编译器选项等。如果您查看stdint.h中声明的类型。这是standard library的一部分,因此(尽管在技术上无法保证)它有望在所有地方都可用。此处声明的类型包括int8_tuint8_tint16_tuint16_tint32_tuint32_tint64_t和{ {1}}。

答案 2 :(得分:0)

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