我最近对以下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.我做错了什么?
托梅克
答案 0 :(得分:3)
这是因为表达式中的参数指定为 而不是 以按任何特定顺序进行评估。
编译器可以首先执行参数k
或lol(&k)
。该表达式中没有序列点。 这意味着参数的副作用可以按任何顺序执行。
简而言之,没有指定代码是打印5
还是10
。两者都是有效的输出。
此例外是布尔表达式中的短路,因为&&
和||
是序列点。 (见评论)
答案 1 :(得分:3)
此代码产生5或10,取决于函数调用的评估值相对于+左侧的选择。
它的行为 not 未定义,因为函数调用被两个序列点包围。
答案 2 :(得分:2)
Plus
是可交换的,因此示例中的顺序完全是实现定义的。
Mysticial 是对的。引用Wikipedia article(手头没有C ++标准):
命令式编程中的序列点定义了a中的任何点 计算机程序的执行,保证所有方面 以前的评估结果将会被执行,而且没有任何一方 已经进行了后续评估的效果。他们是 经常提到参考C和C ++,因为结果有些 表达式可以取决于它们的评估顺序 子表达式。添加一个或多个序列点是一种方法 确保一致的结果,因为这限制了可能的结果 评估令。
该文章还有一个C ++中的序列点列表。