是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。
当前回答
…记得不能用令我惊讶的是,没有人意识到编译器会简单地优化测试,并将一个固定的结果作为返回值。这使得前面答案中的所有代码示例实际上都是无用的。
唯一会返回的是编译时的字节序!是的,我在之前的回答中测试了所有的例子。下面是一个使用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和屏蔽位来做到这一点,但可能最简单的方法是使用内置的网络字节转换操作(因为网络字节顺序总是大端序)。
if ( htonl(47) == 47 ) {
// Big endian
} else {
// Little endian.
}
一点点摆弄可能会更快,但这种方法简单,直接,几乎不可能搞砸。
这通常在编译时(特别是出于性能原因)通过使用编译器提供的头文件或创建自己的头文件来完成。在Linux上,你有头文件“/usr/include/ endan .h”。
要了解更多细节,你可能想要查看这篇codeproject文章Endianness的基本概念:
如何在运行时动态测试Endian类型? 正如《计算机》中解释的那样 动画FAQ,可以使用 下面的函数看看你的代码 是在小端还是大端运行 系统:崩溃 定义BIG_ENDIAN 0 #定义LITTLE_ENDIAN
int TestByteOrder()
{
short int word = 0x0001;
char *byte = (char *) &word;
return(byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
}
这段代码将值0001h赋给a 16位整数。然后是char指针 第一次分配给点 的(最低有效)字节 整数值。的第一个字节 整数是0x01h,然后系统 是Little-Endian (0x01h在 最低或最不重要, 地址)。如果是0x00h,则 系统是大端的。
正如Coriiander所指出的,这里的大部分(如果不是全部的话)代码将在编译时被优化掉,因此生成的二进制文件不会在运行时检查“字节顺序”。
据观察,给定的可执行文件不应该以两个不同的字节顺序运行,但我不知道是否总是这样,对我来说,在编译时检查似乎是一种hack。所以我编写了这个函数:
#include <stdint.h>
int* _BE = 0;
int is_big_endian() {
if (_BE == 0) {
uint16_t* teste = (uint16_t*)malloc(4);
*teste = (*teste & 0x01FE) | 0x0100;
uint8_t teste2 = ((uint8_t*) teste)[0];
free(teste);
_BE = (int*)malloc(sizeof(int));
*_BE = (0x01 == teste2);
}
return *_BE;
}
MinGW无法优化这段代码,尽管它确实优化了这里的其他代码。我相信这是因为我保留了分配在较小字节内存上的“随机”值(至少有7位),所以编译器无法知道这个随机值是什么,也不会优化函数。
我还对函数进行了编码,以便只执行一次检查,并为下一次测试存储返回值。
参见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;
}