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


当前回答

参见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;
} 

其他回答

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

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

你可以通过设置int和屏蔽位来做到这一点,但可能最简单的方法是使用内置的网络字节转换操作(因为网络字节顺序总是大端序)。

if ( htonl(47) == 47 ) {
  // Big endian
} else {
  // Little endian.
}

一点点摆弄可能会更快,但这种方法简单,直接,几乎不可能搞砸。

除非你使用的框架已经移植到PPC和英特尔处理器上,否则你将不得不进行条件编译,因为PPC和英特尔平台拥有完全不同的硬件架构、管道、总线等。这使得两者的程序集代码完全不同。

至于查找字节序,请执行以下操作:

short temp = 0x1234;
char* tempChar = (char*)&temp;

您可以让tempChar为0x12或0x34,从中可以知道字节序。

我很惊讶没有人提到预处理器默认定义的宏。但这取决于你的平台;它们比你自己写尾票要干净得多。

例如;如果我们看看GCC定义的内置宏(在x86-64机器上):

:| gcc -dM -E -x c - | grep -i endian

#define __LITTLE_ENDIAN__ 1

在PPC机器上,我得到:

:| gcc -dM -E -x c - | grep -i endian

#define __BIG_ENDIAN__ 1
#define _BIG_ENDIAN 1

(The:| gcc - dm - e -x c - magic打印出所有内置宏。)

这是另一个C版本。它定义了一个名为wickd_cast()的宏,用于通过C99联合字面值和非标准__typeof__操作符实现内联类型双关语。

#include <limits.h>

#if UCHAR_MAX == UINT_MAX
#error endianness irrelevant as sizeof(int) == 1
#endif

#define wicked_cast(TYPE, VALUE) \
    (((union { __typeof__(VALUE) src; TYPE dest; }){ .src = VALUE }).dest)

_Bool is_little_endian(void)
{
    return wicked_cast(unsigned char, 1u);
}

如果整数是单字节值,则字节顺序没有意义,并将生成编译时错误。