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


当前回答

除非端标头只支持gcc,否则它提供了可以使用的宏。

#include "endian.h"
...
if (__BYTE_ORDER == __LITTLE_ENDIAN) { ... }
else if (__BYTE_ORDER == __BIG_ENDIAN) { ... }
else { throw std::runtime_error("Sorry, this version does not support PDP Endian!");
...

其他回答

c++的方法是使用Boost,在Boost中,预处理器检查和类型转换被划分到经过非常彻底测试的库中。

Predef库(boost/ Predef .h)识别四种不同的字节序。

end - dian库计划提交给c++标准,支持对end -sensitive数据的各种操作。

正如前面的回答所述,Endianness将成为c++ 20的一部分。

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

例如;如果我们看看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打印出所有内置宏。)

如果你不想要条件编译,你可以写独立的代码。下面是一个例子(摘自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

声明:

nonmacro, C++11解:

union {
  uint16_t s;
  unsigned char c[2];
} constexpr static  d {1};

constexpr bool is_little_endian() {
  return d.c[0] == 1;
}

正如Coriiander所指出的,这里的大部分(如果不是全部的话)代码将在编译时被优化掉,因此生成的二进制文件不会在运行时检查“字节顺序”。

据观察,给定的可执行文件不应该以两个不同的字节顺序运行,但我不知道是否总是这样,对我来说,在编译时检查似乎是一种hack。所以我编写了这个函数:

#include <stdint.h>

int* _BE = 0;

int is_big_endian() {
    if (_BE == 0) {
        uint16_t* teste = (uint16_t*)malloc(4);
        *teste = (*teste & 0x01FE) | 0x0100;
        uint8_t teste2 = ((uint8_t*) teste)[0];
        free(teste);
        _BE = (int*)malloc(sizeof(int));
        *_BE = (0x01 == teste2);
    }
    return *_BE;
}

MinGW无法优化这段代码,尽管它确实优化了这里的其他代码。我相信这是因为我保留了分配在较小字节内存上的“随机”值(至少有7位),所以编译器无法知道这个随机值是什么,也不会优化函数。

我还对函数进行了编码,以便只执行一次检查,并为下一次测试存储返回值。