为了账号安全,请及时绑定邮箱和手机立即绑定

在编译时确定字节序

/ 猿问

在编译时确定字节序

C
繁华开满天机 2019-11-15 21:12:54

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

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


查看完整描述

3 回答

?
红颜莎娜

这是用于编译时检查


您可以使用来自boost头文件的信息,该文件endian.hpp涵盖许多平台。


编辑以进行运行时检查


bool isLittleEndian()

{

    short int number = 0x1;

    char *numPtr = (char*)&number;

    return (numPtr[0] == 1);

}

创建一个整数,并读取其第一个字节(最低有效字节)。如果该字节为1,则系统为小端,否则为大端。


编辑思考


是的,您可能会在某些平台(想不到)中遇到潜在问题sizeof(char) == sizeof(short int)。您可以使用可在中使用的固定宽度的多字节整数类型<stdint.h>,或者如果您的平台不提供这种类型,则可以再次使用boost标头供您使用:stdint.hpp


查看完整回答
反对 回复 2019-11-15
?
慕标5265247

为了回答最初的编译时检查问题,没有一种标准化的方法可以在所有现有和将来的所有编译器中使用,因为现有的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

如果您无法从编译器的文档中找到编译器使用的预定义宏,则也可以尝试强制其吐出其预定义宏的完整列表,然后从那里猜测将起作用(使用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)

最后,要解决这个问题,Microsoft Visual C / C ++编译器很奇怪,没有上述任何内容。幸运的是,它们已经在此处记录了预定义的宏,您可以使用目标处理器体系结构来推断字节序。尽管所有在Windows中目前支持的处理器是小端(_M_IX86,_M_X64,_M_IA64,和_M_ARM是小端),喜欢的PowerPC一些历来支持处理器(_M_PPC)为大端。但更相关的是,Xbox 360是一台大端的PowerPC机器,因此,如果您要编写跨平台的库标头,则可以轻松地进行检查_M_PPC。


查看完整回答
反对 回复 2019-11-15
?
45度呼吸

使用C99,您可以执行以下检查:


#define I_AM_LITTLE (((union { unsigned x; unsigned char c; }){1}).c)

类似的条件if (I_AM_LITTLE)将在编译时进行评估,并允许编译器优化整个块。


对于这是否严格来说是C99中的一个常数表达式(这将使它可以用于静态存储持续时间数据的初始化程序),我没有合适的参考资料,但是如果没有,这是下一个最好的选择。


查看完整回答
反对 回复 2019-11-15

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信