且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么在c ++中未指定函数参数的求值顺序?

更新时间:2023-11-11 18:00:46

允许编译器重新排序操作数



假设处理器可以:




  • 每个周期发出一个指令。

  • 在1个周期内执行一次添加。

  • 在3个周期内执行乘法。

  • 可以同时执行添加和乘法。



现在假设你有一个函数调用如下:

  foo(a + = 1, b + = 2,c + = 3,d * = 10); 

如果您在处理器上执行此从左到右,而不 OOE

 循环 - 操作
0 - a + = 1
1 - b + = 2
2 - c + = 3
3 - d * = 10
4 - d * 10
5 - d * = 10

现在如果允许编译器重新排序

 循环 - 操作
0 - d * = 10
1 - a + = 1,d * = 10
2 - b + = 2,d * = 10
3 - c + = 3

所以6个循环与4个循环。



这是完全设计的。现代处理器比这更复杂。但你得到了想法。


The standard doesn't specify the order of evaluation of arguments with this line:

The order of evaluation of arguments is unspecified.

What does

Better code can be generated in the absence of restrictions on expression evaluation order

imply?

What is the drawback in asking all the compilers to evaluate the function arguments Left to Right for example? What kinds of optimizations do compilers perform because of this unspecified spec?

Allowing the compiler to re-order the evaluation of the operands adds more room for optimization.

Here's a completely made up example for illustration purposes.

Suppose the processor can:

  • Issue 1 instruction each cycle.
  • Execute an addition in 1 cycle.
  • Execute a multiplication in 3 cycles.
  • Can execute additions and multiplications at the same time.

Now suppose you have a function call as follows:

foo(a += 1, b += 2, c += 3, d *= 10);

If you were to execute this left-to-right on a processor without OOE:

Cycle - Operation
0     -    a += 1
1     -    b += 2
2     -    c += 3
3     -    d *= 10
4     -    d *= 10
5     -    d *= 10

Now if you allow the compiler to re-order them: (and start the multiplication first)

Cycle - Operation
0     -    d *= 10
1     -    a += 1, d *= 10
2     -    b += 2, d *= 10
3     -    c += 3

So 6 cycles vs. 4 cycles.

Again this is completely contrived. Modern processors are much more complicated than that. But you get the idea.