是否有一种编程方法来检测您使用的是大端序还是小端序体系结构?我需要能够编写将在英特尔或PPC系统上执行的代码,并使用完全相同的代码(即,没有条件编译)。
当前回答
你也可以通过预处理器使用Boost头文件来做到这一点,这可以在Boost endian中找到。
其他回答
不要使用联合号!
c++不允许通过联合的类型双关语! 从不是最后写入的联合字段读取是未定义的行为! 许多编译器支持这样做作为扩展,但语言不能保证。
更多细节请参见以下答案:
https://stackoverflow.com/a/11996970
只有两个有效的答案可以保证是可移植的。
第一个答案,如果你有一个支持c++ 20的系统, 是从<bit>标头使用std::endian。
C++20 起
constexpr bool is_little_endian = (std::endian::native == std::endian::little);
在c++ 20之前,唯一有效的答案是存储一个整数,然后通过类型双关检查它的第一个字节。 与联合的使用不同,这是c++类型系统明确允许的。
同样重要的是要记住,为了获得最佳的可移植性,应该使用static_cast, 因为reinterpret_cast是实现定义的。
如果程序试图通过非下列类型之一的glvalue访问对象的存储值,则行为未定义: ... char或unsigned char类型。
c++ 11 Onwards
enum class endianness
{
little = 0,
big = 1,
};
inline endianness get_system_endianness()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01) ? endianness::little : endianness::big;
}
c++ 11开始(没有enum)
inline bool is_system_little_endian()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}
c++ 98 / c++ 03
inline bool is_system_little_endian()
{
const int value = 0x01;
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}
请看这篇文章:
这里有一些代码来确定是什么 您的机器类型 Int num = 1; If (*(char *)&num == 1) { printf (" \ nLittle-Endian \ n "); } 其他的 { printf(“大端\ n”); }
我正在阅读教科书《计算机系统:程序员的视角》,有一个问题是要确定这是由C程序编写的。
我使用指针的特性来这样做:
#include <stdio.h>
int main(void){
int i=1;
unsigned char* ii = &i;
printf("This computer is %s endian.\n", ((ii[0]==1) ? "little" : "big"));
return 0;
}
因为int占用4个字节,而char只占用1个字节。我们可以使用char指针指向值为1的int类型。因此,如果计算机是小端序的,则char指针所指向的char值为1,否则,其值应为0。
如果你不想要条件编译,你可以写独立的代码。下面是一个例子(摘自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
你可以通过设置int和屏蔽位来做到这一点,但可能最简单的方法是使用内置的网络字节转换操作(因为网络字节顺序总是大端序)。
if ( htonl(47) == 47 ) {
// Big endian
} else {
// Little endian.
}
一点点摆弄可能会更快,但这种方法简单,直接,几乎不可能搞砸。