是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。
当前回答
bool isBigEndian()
{
static const uint16_t m_endianCheck(0x00ff);
return ( *((const uint8_t*)&m_endianCheck) == 0x0);
}
其他回答
除非端标头只支持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!");
...
我不喜欢基于类型双关的方法——它经常会被编译器警告。这正是工会存在的意义!
bool is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
这个原则等同于其他人建议的类型大小写,但这更清楚——并且根据C99,它保证是正确的。与直接指针强制转换相比,GCC更喜欢这种方法。
这也比在编译时修复字节序要好得多——对于支持多架构的操作系统(例如Mac OS X上的胖二进制),这对ppc/i386都适用,否则很容易把事情搞砸。
…记得不能用令我惊讶的是,没有人意识到编译器会简单地优化测试,并将一个固定的结果作为返回值。这使得前面答案中的所有代码示例实际上都是无用的。
唯一会返回的是编译时的字节序!是的,我在之前的回答中测试了所有的例子。下面是一个使用Microsoft Visual c++ 9.0 (Visual Studio 2008)的示例。
纯C代码
int32 DNA_GetEndianness(void)
{
union
{
uint8 c[4];
uint32 i;
} u;
u.i = 0x01020304;
if (0x04 == u.c[0])
return DNA_ENDIAN_LITTLE;
else if (0x01 == u.c[0])
return DNA_ENDIAN_BIG;
else
return DNA_ENDIAN_UNKNOWN;
}
拆卸
PUBLIC _DNA_GetEndianness
; Function compile flags: /Ogtpy
; File c:\development\dna\source\libraries\dna\endian.c
; COMDAT _DNA_GetEndianness
_TEXT SEGMENT
_DNA_GetEndianness PROC ; COMDAT
; 11 : union
; 12 : {
; 13 : uint8 c[4];
; 14 : uint32 i;
; 15 : } u;
; 16 :
; 17 : u.i = 1;
; 18 :
; 19 : if (1 == u.c[0])
; 20 : return DNA_ENDIAN_LITTLE;
mov eax, 1
; 21 : else if (1 == u.c[3])
; 22 : return DNA_ENDIAN_BIG;
; 23 : else
; 24 : return DNA_ENDIAN_UNKNOWN;
; 25 : }
ret
_DNA_GetEndianness ENDP
END
也许可以为这个函数关闭任何编译时优化,但我不知道。否则,也许可以在汇编中硬编码,尽管那是不可移植的。即使这样,这个也可能被优化掉。这让我觉得我需要一些非常蹩脚的汇编器,为所有现有的cpu /指令集实现相同的代码,以及....不要紧。
此外,这里有人说,字节序在运行时不会改变。错了。现在有双端机器。它们的字节顺序在执行期间可以变化。而且,不仅有小端和大端,还有其他端。
声明一个int变量:
int variable = 0xFF;
现在使用char*指针指向它的各个部分,并检查这些部分中有什么。
char* startPart = reinterpret_cast<char*>( &variable );
char* endPart = reinterpret_cast<char*>( &variable ) + sizeof( int ) - 1;
根据哪一个指向0xFF字节,现在您可以检测到字节顺序。这需要sizeof(int) > sizeof(char),但对于所讨论的平台绝对是正确的。
你可以通过设置int和屏蔽位来做到这一点,但可能最简单的方法是使用内置的网络字节转换操作(因为网络字节顺序总是大端序)。
if ( htonl(47) == 47 ) {
// Big endian
} else {
// Little endian.
}
一点点摆弄可能会更快,但这种方法简单,直接,几乎不可能搞砸。