Ada*_*eld 34
为了回答编译时检查的原始问题,没有标准化的方法可以在所有现有和所有未来的编译器中使用,因为现有的C,C++和POSIX标准都没有定义用于检测字节序的宏.
但是,如果您愿意将自己局限于某些已知的编译器,您可以查找每个编译器的文档,找出它们用于定义字节序的预定义宏(如果有的话). 这个页面列出了你可以寻找的几个宏,所以这里有一些代码适用于那些:
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || \
defined(__THUMBEB__) || \
defined(__AARCH64EB__) || \
defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
// It's a big-endian target architecture
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
defined(__LITTLE_ENDIAN__) || \
defined(__ARMEL__) || \
defined(__THUMBEL__) || \
defined(__AARCH64EL__) || \
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
// It's a little-endian target architecture
#else
#error "I don't know what architecture this is!"
#endif
Run Code Online (Sandbox Code Playgroud)
如果您无法从其文档中找到编译器使用的预定义宏,您还可以尝试强制它来吐出其预定义宏的完整列表,并从那里猜测将起作用(使用ENDIAN,ORDER或处理器查找任何内容)它的架构名称). 此页面列出了在不同编译器中执行此操作的许多方法:
Compiler C macros C++ macros
Clang/LLVM clang -dM -E -x c /dev/null clang++ -dM -E -x c++ /dev/null
GNU GCC/G++ gcc -dM -E -x c /dev/null g++ -dM -E -x c++ /dev/null
Hewlett-Packard C/aC++ cc -dM -E -x c /dev/null aCC -dM -E -x c++ /dev/null
IBM XL C/C++ xlc -qshowmacros -E /dev/null xlc++ -qshowmacros -E /dev/null
Intel ICC/ICPC icc -dM -E -x c /dev/null icpc -dM -E -x c++ /dev/null
Microsoft Visual Studio (none) (none)
Oracle Solaris Studio cc -xdumpmacros -E /dev/null CC -xdumpmacros -E /dev/null
Portland Group PGCC/PGCPP pgcc -dM -E (none)
Run Code Online (Sandbox Code Playgroud)
最后,为了完善它,Microsoft Visual C/C++编译器是奇怪的,并没有上述任何一个.幸运的是,他们在此处记录了他们的预定义宏,您可以使用目标处理器体系结构来推断字节序.尽管所有在Windows中目前支持的处理器是小端(_M_IX86,_M_X64,_M_IA64,和_M_ARM是小端),喜欢的PowerPC(历史上的一些支持的处理器_M_PPC)为大端.但更相关的是,Xbox 360是一款大端的PowerPC机器,所以如果你正在编写一个跨平台的库头,那么检查就不会有什么坏处_M_PPC.
wkl*_*wkl 32
这是用于编译时检查
您可以使用boost头文件中的信息,该文件endian.hpp涵盖许多平台.
编辑运行时检查
bool isLittleEndian()
{
short int number = 0x1;
char *numPtr = (char*)&number;
return (numPtr[0] == 1);
}
Run Code Online (Sandbox Code Playgroud)
创建一个整数,并读取其第一个字节(最低有效字节).如果该字节为1,则系统为小端,否则为大端.
编辑思考它
是的,你可能会遇到某些平台(无法想到)的潜在问题sizeof(char) == sizeof(short int).您可以使用固定宽度的多字节整数类型<stdint.h>,或者如果您的平台没有它,您可以再次调整一个boost标头供您使用:stdint.hpp
R..*_*R.. 16
使用C99,您可以执行以下检查:
#define I_AM_LITTLE (((union { unsigned x; unsigned char c; }){1}).c)
Run Code Online (Sandbox Code Playgroud)
类似的条件if (I_AM_LITTLE)将在编译时进行评估,并允许编译器优化整个块.
关于这是否严格地说是C99中的常量表达式(这将允许它在静态存储持续时间数据的初始化器中使用),我没有正确的引用,但如果没有,它是下一个最好的事情.
Dan*_*uţă 10
C FAQ中有趣的读物 :
你可能不会.检测字节序的常用技术涉及char或指针的指针或数组,但预处理器算法仅使用长整数,并且没有寻址的概念.另一种诱人的可能性就像是
Run Code Online (Sandbox Code Playgroud)#if 'ABCD' == 0x41424344但这也不可靠.
我想扩展constexpr为C++ 提供函数的答案
union Mix {
int sdat;
char cdat[4];
};
static constexpr Mix mix { 0x1 };
constexpr bool isLittleEndian() {
return mix.cdat[0] == 1;
}
Run Code Online (Sandbox Code Playgroud)
既然mix是constexpr太是编译时间,可以在使用constexpr bool isLittleEndian().应该是安全的使用.
正如@Cheersandhth在下面指出的那样,这些似乎是有问题的.
原因是,它不符合C++ 11-Standard,禁止类型惩罚.一次只能有一个工会成员处于活动状态.使用标准的符合标准的编译器,您将收到错误.
所以,不要在C++中使用它.看来,你可以在C中做到这一点.我把答案留给教育目的:-)因为问题是关于C ...
这假定int大小为4 char秒,并不总是按照下面正确指出的@PetrVepřek给出.为了使您的代码真正可移植,您必须在这里更聪明.这应该足以满足许多情况.请注意,根据定义,sizeof(char)始终是这样1.上面的代码假定sizeof(int)==4.
使用 CMake TestBigEndian作为
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(ENDIAN)
IF (ENDIAN)
# big endian
ELSE (ENDIAN)
# little endian
ENDIF (ENDIAN)
Run Code Online (Sandbox Code Playgroud)
不是在编译期间,而是在运行时期间.这是我写的一个C函数来确定字节序:
/* Returns 1 if LITTLE-ENDIAN or 0 if BIG-ENDIAN */
#include <inttypes.h>
int endianness()
{
union { uint8_t c[4]; uint32_t i; } data;
data.i = 0x12345678;
return (data.c[0] == 0x78);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
#include <stdint.h>
#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
Run Code Online (Sandbox Code Playgroud)
任何体面的优化器都会在编译时解决这个问题。gcc 在-O1.
当然stdint.h是C99。有关 ANSI/C89 可移植性,请参阅 Doug Gwyn 的Instant C9x库。
| 归档时间: |
|
| 查看次数: |
34251 次 |
| 最近记录: |