3

如果这不是一个真正的问题,请随时关闭;)

4

3 回答 3

9

不仅编译器可以重新排序执行(主要是为了优化),大多数现代处理器也这样做。阅读有关执行重新排序和内存屏障的更多信息。

于 2009-05-15T03:30:59.477 回答
5

编译器可以在认为适合优化目的时更改语句的执行顺序,并且此类更改不会改变代码的可观察行为。

一个非常简单的例子——

int func (int value)
{
    int result = value*2;
    if (value > 10)
    {
       return result;
    }
    else
    {
       return 0;
    }
}

一个天真的编译器可以完全按照所示的顺序为此生成代码。首先计算“结果”并仅在原始值大于 10 时返回它(如果不是,“结果”将被忽略 - 不必要地计算)。

但是,一个理智的编译器会看到,只有在“value”大于 10 时才需要计算“result”,因此可以轻松地将计算“value*2”移动到第一个大括号内,并且只有在“value”时才这样做实际上大于 10(不用说,编译器在优化时并没有真正查看 C 代码 - 它在较低级别工作)。

这只是一个简单的例子。可以创建更复杂的示例。很有可能一个 C 函数最终看起来几乎不像它的编译形式的 C 表示,具有足够积极的优化。

于 2009-05-15T04:21:59.400 回答
4

许多编译器使用称为“公共子表达式消除”的东西。例如,如果您有以下代码:

for(int i=0; i<100; i++) {
    x += y * i * 15;
}

编译器会注意到 y * 15 是不变的(它的值不会改变)。所以它将计算 y * 15,将结果保存在寄存器中并将循环语句更改为“x += r0 * i”。这是一个人为的例子,但是在使用数组索引或任何其他基本 + 偏移类型的情况时,您经常会看到这样的表达式。

于 2009-05-15T05:40:26.063 回答