表达式求值顺序

Expression evaluation order

本文关键字:顺序 表达式      更新时间:2023-10-16

我最近被下面的c++代码段弄糊涂了:

#include <cstdio>
int lol(int *k){
  *k +=5;
   return *k;
}
int main(int argc, const char *argv[]){
  int k = 0;
  int w = k + lol(&k);
  printf("%dn", w);
  return 0;
}

看第一行:

int w = k + lol(&k);

直到现在,我认为这个表达式将从左到右进行评估:取k的当前值(在调用lol函数之前为0),然后将其添加到lol函数的结果中。但是编译器证明我错了,w的值是10。即使我把它改成

int w = lol(&k) + k;

的结果仍然是10。我做错了什么?

Tomek

这是因为表达式中的参数是而不是,指定以任何特定顺序求值。

编译器可以自由地先执行参数klol(&k)。在这个表达式中没有序列点。这意味着参数的副作用可以按任意顺序执行

所以简而言之,没有指定代码是打印5还是10。都是有效的输出。

的例外是在布尔表达式中短路,因为&&||是序列点。(见注释)

这段代码的结果是5还是10,取决于函数调用相对于+左侧的求值顺序的选择。

它的行为是不是未定义的,因为函数调用被两个序列点包围。

Plus根据定义是可交换的,因此示例中的顺序完全是由实现定义的。

mystic 在提到序列点时是正确的。引用维基百科文章(手头没有c++标准):

命令式编程中的序列点定义了A中的任意点一种计算机程序的执行,它保证了所有方面的安全先前评估的效果将被执行,没有副作用后续评价的效果尚未执行。他们是在参考C和c++时经常提到,因为结果有些表达式的求值顺序取决于其子表达式。添加一个或多个序列点是一种方法确保一致的结果,因为这限制了可能性求值顺序

本文还提供了c++中序列点的列表。