在编译时确定字节序

有没有一种安全,可移植的方法来确定(在编译期间)要在其上编译程序的平台的字节顺序?我正在用C写作。

[EDIT]感谢您的回答,我决定坚持使用运行时解决方案!


繁华开满天机
浏览 770回答 3
3回答

红颜莎娜

这是用于编译时检查您可以使用来自boost头文件的信息,该文件endian.hpp涵盖许多平台。编辑以进行运行时检查bool isLittleEndian(){&nbsp; &nbsp; short int number = 0x1;&nbsp; &nbsp; char *numPtr = (char*)&number;&nbsp; &nbsp; return (numPtr[0] == 1);}创建一个整数,并读取其第一个字节(最低有效字节)。如果该字节为1,则系统为小端,否则为大端。编辑思考是的,您可能会在某些平台(想不到)中遇到潜在问题sizeof(char) == sizeof(short int)。您可以使用可在中使用的固定宽度的多字节整数类型<stdint.h>,或者如果您的平台不提供这种类型,则可以再次使用boost标头供您使用:stdint.hpp

小唯快跑啊

为了回答最初的编译时检查问题,没有一种标准化的方法可以在所有现有和将来的所有编译器中使用,因为现有的C,C ++和POSIX标准都没有定义用于检测字节序的宏。但是,如果您愿意将自己局限于某些已知的编译器集,则可以查阅这些编译器的每个文档,以找出它们用于定义字节序的预定义宏(如果有)。 该页面列出了您可以查找的几个宏,因此下面的代码适用于这些宏:#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \&nbsp; &nbsp; defined(__BIG_ENDIAN__) || \&nbsp; &nbsp; defined(__ARMEB__) || \&nbsp; &nbsp; defined(__THUMBEB__) || \&nbsp; &nbsp; defined(__AARCH64EB__) || \&nbsp; &nbsp; defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)// It's a big-endian target architecture#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \&nbsp; &nbsp; defined(__LITTLE_ENDIAN__) || \&nbsp; &nbsp; defined(__ARMEL__) || \&nbsp; &nbsp; defined(__THUMBEL__) || \&nbsp; &nbsp; defined(__AARCH64EL__) || \&nbsp; &nbsp; defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)// It's a little-endian target architecture#else#error "I don't know what architecture this is!"#endif如果您无法从编译器的文档中找到编译器使用的预定义宏,则也可以尝试强制其吐出其预定义宏的完整列表,然后从那里猜测将起作用(使用ENDIAN,ORDER或处理器查找任何内容)架构名称)。 本页列出了许多在不同的编译器中执行此操作的方法:Compiler&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C macros&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C++ macrosClang/LLVM&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;clang -dM -E -x c /dev/null&nbsp; &nbsp; &nbsp; clang++ -dM -E -x c++ /dev/nullGNU GCC/G++&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gcc&nbsp; &nbsp;-dM -E -x c /dev/null&nbsp; &nbsp; &nbsp; g++&nbsp; &nbsp; &nbsp;-dM -E -x c++ /dev/nullHewlett-Packard C/aC++&nbsp; &nbsp; &nbsp;cc&nbsp; &nbsp; -dM -E -x c /dev/null&nbsp; &nbsp; &nbsp; aCC&nbsp; &nbsp; &nbsp;-dM -E -x c++ /dev/nullIBM XL C/C++&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xlc&nbsp; &nbsp;-qshowmacros -E /dev/null&nbsp; xlc++&nbsp; &nbsp;-qshowmacros -E /dev/nullIntel ICC/ICPC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;icc&nbsp; &nbsp;-dM -E -x c /dev/null&nbsp; &nbsp; &nbsp; icpc&nbsp; &nbsp; -dM -E -x c++ /dev/nullMicrosoft Visual Studio (none)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (none)Oracle Solaris Studio&nbsp; &nbsp; &nbsp; cc&nbsp; &nbsp; -xdumpmacros -E /dev/null&nbsp; CC&nbsp; &nbsp; &nbsp; -xdumpmacros -E /dev/nullPortland Group PGCC/PGCPP&nbsp; pgcc&nbsp; -dM -E&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(none)最后,要解决这个问题,Microsoft Visual C / C ++编译器很奇怪,没有上述任何内容。幸运的是,它们已经在此处记录了预定义的宏,您可以使用目标处理器体系结构来推断字节序。尽管所有在Windows中目前支持的处理器是小端(_M_IX86,_M_X64,_M_IA64,和_M_ARM是小端),喜欢的PowerPC一些历来支持处理器(_M_PPC)为大端。但更相关的是,Xbox 360是一台大端的PowerPC机器,因此,如果您要编写跨平台的库标头,则可以轻松地进行检查_M_PPC。

开心每一天1111

使用C99,您可以执行以下检查:#define I_AM_LITTLE (((union { unsigned x; unsigned char c; }){1}).c)类似的条件if (I_AM_LITTLE)将在编译时进行评估,并允许编译器优化整个块。对于这是否严格来说是C99中的一个常数表达式(这将使它可以用于静态存储持续时间数据的初始化程序),我没有合适的参考资料,但是如果没有,这是下一个最好的选择。
打开App,查看更多内容
随时随地看视频慕课网APP