表达评估顺序

时间:2011-11-24 21:20:18

标签: c++

我最近对以下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("%d\n", w);
  return 0;
}

看一下行:

int w = k + lol(&k);

到目前为止,我认为这个表达式将从左到右进行计算:取k的当前值(在calll到lol函数之前为0)然后将其添加到lol函数的结果中。但编译器证明我错了,w的值是10.即使我切换位置使其成为

int w = lol(&k) + k;

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

托梅克

3 个答案:

答案 0 :(得分:3)

这是因为表达式中的参数指定为 而不是 以按任何特定顺序进行评估。

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

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

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

答案 1 :(得分:3)

此代码产生5或10,取决于函数调用的评估值相对于+左侧的选择。

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

答案 2 :(得分:2)

根据定义,

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

提及序列点时,

Mysticial 是对的。引用Wikipedia article(手头没有C ++标准):

  

命令式编程中的序列点定义了a中的任何点   计算机程序的执行,保证所有方面   以前的评估结果将会被执行,而且没有任何一方   已经进行了后续评估的效果。他们是   经常提到参考C和C ++,因为结果有些   表达式可以取决于它们的评估顺序   子表达式。添加一个或多个序列点是一种方法   确保一致的结果,因为这限制了可能的结果   评估令。

该文章还有一个C ++中的序列点列表。