C++ 在运行时检测endian有什么好处?

C++ 在运行时检测endian有什么好处?,c++,endianness,C++,Endianness,我在计算机上搜索了用于确定endianess的宏,但没有找到任何标准的前处理器宏,但很多解决方案都是在运行时这样做的为什么要在运行时检测endianess? 如果我这样做: 编译器将只生成一个函数 但如果我喜欢(见): 编译器生成用于检测的代码 我不明白,我为什么要这么做 如果我有为小端机器编译的代码,那么整个代码都是为小端机器生成的,如果我尝试在大端机器上运行这样的代码(在像arm这样的双端机器上),那么整个代码都是为小端机器编译的。因此,所有其他声明,例如int,也都是le // comp

我在计算机上搜索了用于确定endianess的宏,但没有找到任何标准的前处理器宏,但很多解决方案都是在运行时这样做的为什么要在运行时检测endianess?

如果我这样做:

编译器将只生成一个函数

但如果我喜欢(见):

编译器生成用于检测的代码

我不明白,我为什么要这么做

如果我有为小端机器编译的代码,那么整个代码都是为小端机器生成的,如果我尝试在大端机器上运行这样的代码(在像arm这样的双端机器上),那么整个代码都是为小端机器编译的。因此,所有其他声明,例如int,也都是le

// compiled on little endian
uint32_t 0x1234;  // 0x1234 constant literal
// should result 34120000 on BE

我认为在运行时检测endianness的唯一好处是,您不必乱动宏。正如您自己所注意到的,没有标准宏说明编译代码的机器的endian是什么,因此您必须自己定义一些内容并将其传递给编译器,或者根据指示体系结构/操作系统的其他标志有条件地定义它,例如:

#ifdef _this_system_
#define LITTLE_ENDIAN
#endif
#ifdef _that_system_
#define BIG_ENDIAN
#endif

但对于每一种可能的体系结构,都会重复多次,这是一种混乱且容易出错的体系结构。在运行时检查它更容易、更安全。我知道,这看起来很傻,但实际上更实用。

实际上有一些系统,软件可以在其中设置系统是(当前运行)little endian模式还是big endian模式。大多数系统只支持在特殊情况下进行切换,而不支持(幸运的是,对于系统程序员等)任意来回切换。但可以想象,支持可执行文件定义特定可执行文件是以LE模式还是be模式运行。在这种情况下,你不能依赖于挑选出它是什么操作系统和处理器型号


另一方面,如果硬件只支持一个端点(例如x86的不同形式),那么我认为不需要在运行时进行检查。你知道是小恩迪安,就是这样。让系统包含代码来检查它是哪一个尾端,并携带从大尾端到小尾端的转换方法,这是一种浪费(在性能和代码大小方面)

在编译时进行健壮的endian检测不一定是可能的。在某些平台上,即使在相同二进制文件的两次运行之间,endianess也可以更改


我想你的意思是它应该会在little endian上产生
34120000
。@MarkB为什么?在LE上编译,在BE上执行。交换应该是相同的。有没有现代机器仍然使用单词交换的尾端符号?或者我可以在编写(反)序列化引擎时忽略它们吗?在处理跨平台项目时,很可能会使用buildsystem生成器(AutoTools、CMake、SCons等)。这也可以用于检测endianness(例如,通过构建和运行一个小程序),并将适当的定义传递给编译器。当然,我相信cmake和类似的系统可以提供一个健壮的编译时解决方案,因此如果您使用这样的系统,您可以试试。@Angew如果您想允许交叉编译,请小心。+1就是这样一种架构。我知道至少可以为“将endian设置为此”配置一些ARM和MIPS以及现在相当不存在的29K处理器范围。尽管需要一些仔细的计划才能使其正确,否则您将完全返回到杂草丛中的某个地方,并意外地更改它,因为您的代码意外地将一些随机位带入了控制寄存器,但我相信这将导致非常有趣的调试。好的,我不知道。所以它对一些稀有的机器是有用的,但对我来说不是。非常感谢。
// compiled on little endian
uint32_t 0x1234;  // 0x1234 constant literal
// should result 34120000 on BE
#ifdef _this_system_
#define LITTLE_ENDIAN
#endif
#ifdef _that_system_
#define BIG_ENDIAN
#endif