为什么现代编译器不合并相邻内存访问以优化逐字节判零逻辑?
这个优化没有被C规范禁止,编译器不执行优化的核心原因是短路求值的语义限制,符合C的as-if优化规则要求。
具体原因如下:
- 原始代码使用的
&&是短路与运算符:只要前面任意一个字节比较结果为非0,会直接返回false,不会访问后续地址的字节。如果buf刚好处于内存页边界,比如buf[0]所在的内存页可读,buf+1起始的下一页是不可访问的保护页,只要第一个字节非0,原始代码不会触发任何非法访问。 - 如果强行优化为单次32位整型比较,无论第一个字节的值是什么,都需要一次性读取4个字节的内存。如果遇到上述页边界场景,会触发原代码完全不会出现的段错误,改变了程序的可观测行为,违反了C++规范要求的
as-if优化原则,因此GCC、MSVC、Clang都不会在使用&&的场景下做这个优化。 - 当你把短路与
&&替换为按位与&后,不存在短路语义,四个字节的比较操作必须全部执行才能得到最终结果,编译器可以确定四个字节一定会被访问,不存在额外的非法访问风险,因此可以合法执行合并访存的优化。
补充说明:如果确认传入的buf地址一定满足32位整型的对齐要求、且不存在页边界访问风险,手动使用强制类型转换做32位比较是完全合法的性能优化手段。
内容的提问来源于stack exchange,提问作者user17507206
相关产品推荐
相关产品推荐

