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


当前回答

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

例如;如果我们看看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++ 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
}

要了解更多细节,你可能想要查看这篇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,则 系统是大端的。

…记得不能用令我惊讶的是,没有人意识到编译器会简单地优化测试,并将一个固定的结果作为返回值。这使得前面答案中的所有代码示例实际上都是无用的。

唯一会返回的是编译时的字节序!是的,我在之前的回答中测试了所有的例子。下面是一个使用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的解决方案。

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

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

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

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