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

use*_*087 3 c++ endianness

我已经搜索了宏以确定机器上的字节顺序,并且没有找到任何标准的预处理器宏,但很多解决方案在运行时都这样做.为什么我应该在运行时检测到endianess?

如果我做那样的事情:

#ifdef LITTLE_ENDIAN
  inline int swap(int& x) {
    // do swap anyhow
    return swapped;
  }
#elif BIG_ENDIAN
  inline int& swap(int& x) { return x; }
#else
  #error "some blabla"
#endif

int main() {
  int x = 0x1234;
  int y = swap(x);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器只生成一个函数.

但如果我这样做(见predef.endian):

enum {
  ENDIAN_UNKNOWN,
  ENDIAN_BIG,
  ENDIAN_LITTLE,
  ENDIAN_BIG_WORD,   /* Middle-endian, Honeywell 316 style */
  ENDIAN_LITTLE_WORD /* Middle-endian, PDP-11 style */
};

int endianness(void)
{
  uint8_t buffer[4];

  buffer[0] = 0x00;
  buffer[1] = 0x01;
  buffer[2] = 0x02;
  buffer[3] = 0x03;

  switch (*((uint32_t *)buffer)) {
  case 0x00010203: return ENDIAN_BIG;
  case 0x03020100: return ENDIAN_LITTLE;
  case 0x02030001: return ENDIAN_BIG_WORD;
  case 0x01000302: return ENDIAN_LITTLE_WORD;
  default:         return ENDIAN_UNKNOWN;
}


int swap(int& x) {
  switch(endianess()) {
    case ENDIAN_BIG:
      return x;
    break;
    case LITTLE_ENDIAN:
      // do swap
      return swapped;
    break;
    default:
      // error blabla
  }
  // do swap anyhow
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果我有代码,为小端机器编译,整个代码是为小端生成的,如果我尝试在big-endian机器上运行这样的代码(在像arm wiki这样的双端机器上:bi-endian)整个代码是为一个小端机器编译的.所以所有其他的例如int的声明也是le.

// compiled on little endian
uint32_t 0x1234;  // 0x1234 constant literal
// should result 34120000 on BE
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 5

实际上,软件可以设置系统是(当前正在运行)小端还是大端模式.大多数系统仅支持在特殊情况下的切换,而不是(幸运的是系统程序员等)任意来回切换.但是可以想象支持可执行文件定义该特定可执行文件是以LE模式还是BE模式运行.在这种情况下,你不能依赖于选择它的操作系统和处理器模型......

另一方面,如果硬件只有EVER支持一个字节序(例如x86的不同形式),那么我认为不需要在运行时检查.你知道它是小端,就是这样.系统包含检查字节序列的代码,并带有转换方法以从大端转换为小端,这是浪费(在性能和代码大小方面).