这段测试大字节序或小字节序的代码是如何工作的?

How does this code that tests for big- or little-endianness work?

我正在研究 Endianness,当我阅读一本教科书时,他们向我提供了这个 运行 时间测试来检查(在 运行 时间)代码是否 运行ning在小端或大端系统上。这本书没有解释任何东西,我很困惑这段代码是如何工作的。谁能帮我解释一下这段代码是如何工作的。提前谢谢你

/* Test platform Endianness */
    int bigendian(void) {
        int i;
        union {
            char Array[4];
            long Chars;
        } TestUnion;
        char c = 'a';

    for(i=0; i<4; i++)
        TestUnion.Array[i] = c++; 
    if (TestUnion.Chars == 0x61626364)
        return 1;
    else
        return 0;
}

假设您正在使用 ASCII 作为其字符集的系统,值 0x610x620x630x64 代表字母abcd

循环:

char c = 'a';

for(i=0; i<4; i++)
    TestUnion.Array[i] = c++; 

abcd 填充并集 TestUnionchar array 部分。如果您在 big-endian 机器上访问联合作为 32 位 long,它将表示为 0x61626364;如果它是 little-endian 多头将是 0x64636261.

不过,这不是一个很好的 "general case" 算法来测试字节顺序,因为:

  1. 并非所有系统都使用 ASCII 来表示字符
  2. 一个long不一定是4*sizeof(char)字节宽

union提供了数据的不同观点——这里的TestUnion可以解释为:

  • 一个char[4]数组,或者
  • a long 整数

for 循环将 TestUnion 填充为 char[4] 数组 - 请注意字符 a 具有 ASCII 代码 0x61b0x62 等等。所以内存中填充了4个字节0x610x620x630x64,每个字节的地址位置都是升序排列的。

if 语句通过将 TestUnion 解释为 long 整数来检查它是否为 BigEndian。如果它是 BigEndian,那么 long int 数字是从 left-to-right 中读取的,它转换为 0x61626364。否则它是 LittleEndian,将从 right-to-left 读取,意思是 0x64636261.

您可以使用以下代码检查系统中的该功能:

printf( "bigendian ? %s\n", bigendian() ? "true" : "false" );

字节顺序是指内存中是低字节先存还是高字节先存。小端机器先存储低字节,大端机器先存储高字节。如果整数有两个以上的字节,其他顺序也是可能的,但非常罕见。

代码所做的是设置联合,以便 char 数组和长整数共享相同的地址 space。然后它通过计算预期值来检查 long 的字节是哪一圈。由于许多原因,它写得不好。从技术上讲,写入联合的一个字段然后从另一个字段读取是未定义的行为。该代码假定 sizeof(long) == 4,ASCII 是字符集,并且编译器将按预期处理联合。可能所有这些都会成立。他还将带符号的值与设置了高位的十六进制值进行比较——我认为这没问题,但这取决于 C 标准的细节。

更好的测试就是

int x = 0xFF;
unsigned char *test = (unsigned char *)&x;
if(test[sizeof(int)-1] == 0xFF)
    /* big-endian */
if(test[sizeof(int)-1] == 0x00)
    /* little-endian */