C语言程序中自增运算符导致的意外结果
为什么
int b = (a) + a++;会得到9而不是8? 核心问题是你把运算符优先级/结合性和表达式求值顺序搞混了,另外还要注意C++标准版本的差异:
1. 先搞懂两个关键概念的区别
- 优先级/结合性:只负责确定表达式的语法结构,也就是哪个操作数属于哪个运算符。比如你说的
(a) + a++,优先级确实会把它解析成(a)和(a++)作为+的两个操作数,这部分你没错,但优先级完全不决定这两个操作数谁先被计算。 - 求值顺序:指的是表达式中各个子表达式的计算顺序,这是由语言标准规定的(或在某些情况下未规定)。
2. 后置++的行为
后置++的规则是:先返回变量当前的数值,之后再把变量的值加1。但这个“加1”的副作用什么时候执行,不是由优先级决定的,而是和求值顺序绑定。
3. 不同C++标准下的结果差异
情况1:C++17之前的标准
在C++17之前,对于+这类二元运算符,语言标准没有规定左操作数和右操作数的求值顺序,而且像(a) + a++这种代码,同一个变量a在没有序列点的情况下,既被读取(左边的a)又被修改(a++的副作用),属于未定义行为。
这意味着编译器可以自由选择计算顺序:
- 如果先算左边的
(a),得到4,再算a++(返回4,a变成5),结果就是4+4=8(你的预期)。 - 如果先算右边的
a++(返回4,a立刻变成5),再算左边的(a),此时a已经是5了,结果就是5+4=9(你实际看到的)。
编译器甚至可以输出其他结果,因为未定义行为没有任何限制。
情况2:C++17及之后的标准
C++17对求值顺序做了明确规定:对于内置的二元+运算符,左操作数必须先于右操作数完成求值(包括所有副作用)。
所以在C++17及以后,(a) + a++的结果是确定的8:先计算左边的a(值为4),再计算右边的a++(返回4,随后a变成5),相加得到8。
4. 总结
你看到结果为9,大概率是因为使用了遵循C++17之前标准的编译器,它选择了先计算右操作数a++,导致左边的a读取到了已经自增后的值。这种代码本身在旧标准下属于未定义行为,不应该写出这样的代码——如果要明确逻辑,应该把自增操作拆分到单独的语句里,比如:
int a = 4; int temp = a; a++; int b = temp + temp; // 按你预期的逻辑,或者 temp + a 按自增后的逻辑
内容的提问来源于stack exchange,提问作者Osmium
相关产品推荐
相关产品推荐

