我有一个性能关键的C代码需要在各种平台上工作。 其中一些是小端,另一些是大端。
基于宏观检测,检测字节序目前是不完美的过程。 但很难确定宏检测是否适用于系统和编译器的所有组合。 欢迎来到便携式代码世界。
检测endianess的一种相对安全的方法是使用运行时测试,并希望它将被编译器优化。 这些方面的东西:
static const int one = 1; #define IS_LITTLE_ENDIAN (*(char*)(&one))
一般来说它有效。 编译器应正确检测到该宏的结果对于给定的体系结构总是相同的(1表示小端,0表示大端),只需完全删除内存访问和关联的分支。
我的问题是:总是如此吗? 我们是否可以期望编译器始终正确理解此测试,并始终正确地优化它? (假设-O2 / -O3或等效的优化级别,当然不适用于调试代码)
我特别担心双端CPU ,比如ARM。 由于这样的CPU可以是大端或小端,取决于OS参数,编译器可能难以“硬连线”这样的端序测试。 另一方面,我不希望应用程序以“任一端选择模式”工作:我想它应该编译为一个精确和明确的endianess。 因此,IS_LITTLE_ENDIAN应始终保持相同。
无论如何,我要求遇到遇到这种情况的人的经历。 由于我目前没有双端CPU和编译器,我无法测试并观察上述假设。
[ 编辑 ] @Brandin建议“保存宏的结果”,使其成为一个变量。 我猜他提出这样的事情:
static const int one = 1; static const int isLittleEndian = *(char*)(&one);
由于在编译时会计算静态const int,因此确实可以保证编译器必须知道isLittleEndian的值,因此可以正确地优化使用此变量的分支。
不幸的是,它不起作用。 上述声明导致以下编译错误:
error: initializer element is not constant
我想这是因为在编译时无法评估一个(指针地址)。
@ HuStmpHrrr的变体,使用union,看起来更好:没有要评估的指针地址。 不幸的是,它不能更好地工作,并导致相同的编译错误。
我想这是因为编译器认为联合不够简单,不能用作静态const初始化的值。
所以我们回到了开头,用宏来代替。
同样的想法,但不同的技巧。 这段代码也可以。
union { int num; char[sizeof(int)] bytes; } endian; endian.num = 1;
然后使用endian.bytes[0]
来判断。
这样,事情变得更加自然,编译器应该做一些事情,因为这很容易被简单的数据流优化器实现跟踪。
endian.bytes[0]
应该缩小为常数。
无论如何,这种方式依赖于编译器。
我忽略了@OliCharlesworth在评论中链接的post中的小问题,我同意它的精神:你确定字节顺序真的很重要,如果确实如此,为什么呢?
除了“我有性能关键代码”之外没有更多上下文,任何其他指导都不可用。 我已经提到的主要问题是机器的字节顺序对于这个问题如此重要的原因。
您可以使用htonl来检测它:
#include int main() { if (htonl(1) == 1) printf("big endiann"); else printf("little endiann"); }
以上就是c/c++开发分享C中的endianess检测和性能相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/549276.html