是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。
当前回答
如果你不想要条件编译,你可以写独立的代码。下面是一个例子(摘自Rob Pike):
以独立于端序的方式读取磁盘上以little-endian方式存储的整数:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
同样的代码,试图考虑到机器的字节顺序:
i = *((int*)data);
#ifdef BIG_ENDIAN
/* swap the bytes */
i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0);
#endif
其他回答
如果你可以使用c++ 20编译器,比如GCC 8+或Clang 7+,你可以使用std::endian。
注意:std::endian从<type_traits>开始,但在2019年科隆会议上被移动到<bit>。GCC 8、Clang 7、8、9在<type_traits>, GCC 9+和Clang 10+在<bit>。
#include <bit>
if constexpr (std::endian::native == std::endian::big)
{
// Big-endian system
}
else if constexpr (std::endian::native == std::endian::little)
{
// Little-endian system
}
else
{
// Something else
}
请看这篇文章:
这里有一些代码来确定是什么 您的机器类型 Int num = 1; If (*(char *)&num == 1) { printf (" \ nLittle-Endian \ n "); } 其他的 { printf(“大端\ n”); }
除非你使用的框架已经移植到PPC和英特尔处理器上,否则你将不得不进行条件编译,因为PPC和英特尔平台拥有完全不同的硬件架构、管道、总线等。这使得两者的程序集代码完全不同。
至于查找字节序,请执行以下操作:
short temp = 0x1234;
char* tempChar = (char*)&temp;
您可以让tempChar为0x12或0x34,从中可以知道字节序。
…记得不能用令我惊讶的是,没有人意识到编译器会简单地优化测试,并将一个固定的结果作为返回值。这使得前面答案中的所有代码示例实际上都是无用的。
唯一会返回的是编译时的字节序!是的,我在之前的回答中测试了所有的例子。下面是一个使用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 /指令集实现相同的代码,以及....不要紧。
此外,这里有人说,字节序在运行时不会改变。错了。现在有双端机器。它们的字节顺序在执行期间可以变化。而且,不仅有小端和大端,还有其他端。
union {
int i;
char c[sizeof(int)];
} x;
x.i = 1;
if(x.c[0] == 1)
printf("little-endian\n");
else
printf("big-endian\n");
这是另一个解。类似于Andrew Hare的解决方案。