如何在所有原始整数大小相同的系统上检测字节顺序?

时间:2011-01-17 11:02:13

标签: c puzzle endianness

(这个问题来自昨天向某人解释CHAR_BIT,sizeof和endianness的细节。这完全是假设的。)

假设我在一个CHAR_BIT为32的平台上,所以sizeof(char)== sizeof(short)== sizeof(int)== sizeof(long)。我相信这仍然是一个符合标准的环境。

在运行时(because there is no reliable way to do it at compile time)检测字节顺序的常用方法是创建union { int i, char c[sizeof(int)] } x; x.i = 1并查看是否设置了x.c[0]x.c[sizeof(int)-1]

但是这在这个平台上不起作用,因为我最终得到了一个char [1]。

有没有办法在运行时检测这样的平台是big-endian还是little-endian?显然,在这个假设系统中没有关系,但可以想象它正在写入一个文件,或某种内存映射区域,另一台机器根据其(更精确的)内存模型读取并重建它。

8 个答案:

答案 0 :(得分:4)

假设,在所有数据类型大小相同的环境中,没有字节顺序。

我可以看到三种可能性:

  • 如果限制仅由C编译器提供,并且从技术上讲,平台有一些较小的数据类型,则可以使用汇编程序来检测字节序。

  • 如果平台支持双数据类型,您可以使用它来检测字节序,因为它总是64位宽。

  • 您也可以按照建议将数据写入文件,然后回读。只需编写两个字符(二进制模式下的文件),将文件指针移动到位置1并读回一个字符。

答案 1 :(得分:4)

字节序的概念仅对由多个字节表示的标量类型有意义。根据定义,char是单字节的,因此任何与char具有相同大小的整数类型都没有字节序。

还要记住,不同类型的字节顺序可能不同:例如,PDP-11是一个小端16位架构,32位整数是由两个16位小端值构建的,结束混合端。

答案 2 :(得分:2)

我认为这个问题归结为:字节序在这个平台上是一个有意义的概念,即它是否对程序的行为有可检测的影响?

如果没有,那么字节顺序(即构成32位数量的单个字节存储在内存中的顺序)仅仅是一个你无法检测但不需要考虑的实现细节。你要么。

如果字节序确实对语言的某个方面的行为有可检测的影响......那么,然后根据该行为构建测试。以下是一些例子:

  • 平台上的寻址系统如何工作?如果将地址递增1,那么对应的位数是多少?如果答案是8位且系统允许您从不是4的倍数的地址读取,那么您可以将指针向前移动一个字节(通过绕道到intptr_t)并测试字节顺序那样。 (是的,这是实现定义的行为,但是使用union来测试endianness以及一般的endianness的整个概念。)但是,如果内存的最小可寻址单位是32字节,那么你可以'以这种方式测试字节顺序。

  • 平台是否具有64位数据类型(long long)?然后,您可以创建long long和两个int的联合,并根据该联合构建您的字节顺序测试。

答案 3 :(得分:0)

结构位域仍然可以在任何平台上正常工作,即使是这个:

union {
   int i;
   struct {
       int b1 : 8;
       int b2 : 8;
       int b3 : 8;
       int b4 : 8;
   } s;
} u;

u.i = 1;
if (u.s.b1 != 0)
   ....

答案 4 :(得分:0)

这个问题没有提供足够的信息,但它提供了什么,我会说:不可能。

答案 5 :(得分:0)

htonl应该有效:

if(htonl(1)==1) {
   /* network order (big-endian) */
} else {
   /* little-endian */
}

(我看不出有任何理由不以通常的方式实施htonl和朋友,即使对于这个讨厌的假设系统 - 尽管我不确定他们会有多少帮助做法。)

答案 6 :(得分:0)

您可以移动有问题的变量,看看1的哪一端移开。

答案 7 :(得分:-1)

如果你的代码依赖于知道架构是BE还是LE,那么你的代码应该具有安全性,而不是针对未知平台进行编译。有些#if ! defined(ARCH_IS_LE) && ! defined(ARCH_IS_BE) \ #error unknown architecture应该这样做。