标准没有指定对参数的评估顺序。
参数的评估顺序是未指定的。
“在没有对表达式评估顺序的限制下,可以生成更好的代码”这句话意味着什么?
如果要求所有编译器按照从左到右的顺序评估函数参数,会有什么缺点?由于这个未指定的规范,编译器会进行哪些优化?
参数的评估顺序是未指定的。
“在没有对表达式评估顺序的限制下,可以生成更好的代码”这句话意味着什么?
如果要求所有编译器按照从左到右的顺序评估函数参数,会有什么缺点?由于这个未指定的规范,编译器会进行哪些优化?
允许编译器重新排列操作数的评估顺序,为优化提供了更多的空间。
这里是一个完全虚构的示例,仅供说明目的。
假设处理器可以:
现在,假设你有一个函数调用,如下所示:
foo(a += 1, b += 2, c += 3, d *= 10);
如果您在没有乱序执行的处理器上从左到右执行此操作:
Cycle - Operation
0 - a += 1
1 - b += 2
2 - c += 3
3 - d *= 10
4 - d *= 10
5 - d *= 10
如果您允许编译器重新排序它们:(并首先开始乘法)
Cycle - Operation
0 - d *= 10
1 - a += 1, d *= 10
2 - b += 2, d *= 10
3 - c += 3
所以是6周期对4周期。
再次强调,这完全是虚构的。现代处理器比这复杂得多。但你能理解这个思路。
// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);
p
进行两次解引用(并根据结果进行一些计算)并调用 bar
一次。如果编译器很聪明,它可能会重新排序求值顺序。int temp = *p * 3;
foo(temp, bar(), temp + 1);
这样它只需要做一次“解引用,乘以3”的操作。这被称为公共子表达式消除。
p
的值不会改变。当然,在C内存模型中,这几乎是不可能保证的,这可能就是为什么需要未定义的求值顺序来实现这种优化的原因。 - Joey