我们知道逻辑与运算符 (&&
) 保证从左到右的计算。
但我想知道编译器优化器是否可以在以下代码中重新排序 *a
和 b->foo
的内存访问指令,即优化器编写指令在访问 *a
之前尝试访问 *b
。
(将a
和b
都视为指向堆中内存区域的指针。)
if (*a && b->foo) {
/* do something */
}
有人可能会认为 &&
会导致序列点,因此编译器必须在访问 *b
之前发出访问 *a
的指令,但之后在 https://stackoverflow.com/a/14983432/1175080 阅读已接受的答案,我不太确定。如果你看一下这个答案,语句之间有分号,它们也建立了序列点,因此它们也应该防止重新排序,但那里的答案似乎表明尽管存在分号,它们仍需要编译器级别的内存屏障。
我的意思是,如果您声称 &&
建立了一个序列点,那么 https://stackoverflow.com/a/14983432/1175080 处的代码中的分号也是如此。 .那为什么在该代码中需要编译器级别的内存屏障?
最佳答案
系统可以评估 b->foo
直到它遇到超出其推测执行能力的东西。大多数现代系统都可以处理推测性故障,并在事实证明从未使用过操作结果时忽略该故障。
所以这完全取决于编译器、CPU 和其他系统组件的能力。只要它能确保合规代码没有明显的后果,它就可以(几乎)在任何时候执行(几乎)它想要的任何东西。
关于C 编译器优化器能否违反逻辑与表达式中操作数的短路和重新排序内存访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38061281/