是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。


当前回答

我正在阅读教科书《计算机系统:程序员的视角》,有一个问题是要确定这是由C程序编写的。

我使用指针的特性来这样做:

#include <stdio.h>

int main(void){
    int i=1;
    unsigned char* ii = &i;

    printf("This computer is %s endian.\n", ((ii[0]==1) ? "little" : "big"));
    return 0;
}

因为int占用4个字节,而char只占用1个字节。我们可以使用char指针指向值为1的int类型。因此,如果计算机是小端序的,则char指针所指向的char值为1,否则,其值应为0。

其他回答

参见Endianness - c级代码说明。

// assuming target architecture is 32-bit = 4-Bytes
enum ENDIANNESS{ LITTLEENDIAN , BIGENDIAN , UNHANDLE };


ENDIANNESS CheckArchEndianalityV1( void )
{
    int Endian = 0x00000001; // assuming target architecture is 32-bit    

    // as Endian = 0x00000001 so MSB (Most Significant Byte) = 0x00 and LSB (Least     Significant Byte) = 0x01
    // casting down to a single byte value LSB discarding higher bytes    

    return (*(char *) &Endian == 0x01) ? LITTLEENDIAN : BIGENDIAN;
} 

这个怎么样?

#include <cstdio>

int main()
{
    unsigned int n = 1;
    char *p = 0;

    p = (char*)&n;
    if (*p == 1)
        std::printf("Little Endian\n");
    else 
        if (*(p + sizeof(int) - 1) == 1)
            std::printf("Big Endian\n");
        else
            std::printf("What the crap?\n");
    return 0;
}

这是未经测试的,但在我看来,这应该是可行的。因为在小端序上是0x01,在大端序上是0x00。

bool runtimeIsLittleEndian(void)
{
    volatile uint16_t i=1;
    return ((uint8_t*)&i)[0]==0x01; // 0x01=little, 0x00=big
}

除非端标头只支持gcc,否则它提供了可以使用的宏。

#include "endian.h"
...
if (__BYTE_ORDER == __LITTLE_ENDIAN) { ... }
else if (__BYTE_ORDER == __BIG_ENDIAN) { ... }
else { throw std::runtime_error("Sorry, this version does not support PDP Endian!");
...

正如前面的答案所述,使用工会技巧。

但是上面建议的方法也存在一些问题。最值得注意的是,对于大多数架构来说,未对齐的内存访问是出了名的慢,一些编译器甚至根本无法识别这样的常量谓词,除非字对齐。

因为仅仅是端序测试很无聊,这里有一个(模板)函数,它将根据您的规范翻转输入/输出的任意整数,而不考虑主机架构。

#include <stdint.h>

#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0

template <typename T>
T endian(T w, uint32_t endian)
{
    // This gets optimized out into if (endian == host_endian) return w;
    union { uint64_t quad; uint32_t islittle; } t;
    t.quad = 1;
    if (t.islittle ^ endian) return w;
    T r = 0;

    // Decent compilers will unroll this (GCC)
    // or even convert straight into single bswap (Clang)
    for (int i = 0; i < sizeof(r); i++) {
        r <<= 8;
        r |= w & 0xff;
        w >>= 8;
    }
    return r;
};

用法:

要将给定的端序转换为主机,请使用:

Host = endian(source, endian_of_source)

要将主机端序转换为给定端序,请使用:

输出= endian(hostsource, endian_you_want_to_output)

生成的代码与在Clang上编写手动程序集一样快,在GCC上稍微慢一点(展开&,<<,>>,|每个字节),但仍然不错。