是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。
当前回答
你也可以通过预处理器使用Boost头文件来做到这一点,这可以在Boost endian中找到。
其他回答
…记得不能用令我惊讶的是,没有人意识到编译器会简单地优化测试,并将一个固定的结果作为返回值。这使得前面答案中的所有代码示例实际上都是无用的。
唯一会返回的是编译时的字节序!是的,我在之前的回答中测试了所有的例子。下面是一个使用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 /指令集实现相同的代码,以及....不要紧。
此外,这里有人说,字节序在运行时不会改变。错了。现在有双端机器。它们的字节顺序在执行期间可以变化。而且,不仅有小端和大端,还有其他端。
你也可以通过预处理器使用Boost头文件来做到这一点,这可以在Boost endian中找到。
如果你可以使用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
}
c++20解决方案:
constexpr bool compare(auto const c, auto const ...a) noexcept
{
return [&]<auto ...I>(std::index_sequence<I...>) noexcept
{
return ((std::uint8_t(c >> 8 * I) == a) && ...);
}(std::make_index_sequence<sizeof...(a)>());
}
static constexpr auto is_big_endian_v{
compare(std::uint32_t(0x01234567), 0x01, 0x23, 0x45, 0x67)
};
static constexpr auto is_little_endian_v{
compare(std::uint32_t(0x01234567), 0x67, 0x45, 0x23, 0x01)
};
static constexpr auto is_pdp_endian_v{
compare(std::uint32_t(0x01234567), 0x23, 0x01, 0x67, 0x45)
};
这个任务可以更容易地完成,但是由于某种原因,<bit>头文件并不总是存在。这是一个演示。
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的解决方案。