You need to enable JavaScript to run this app. 带赋值运算符的表达式求值顺序问题:为何代码运行结果z=20而非预期19
优惠活动
大模型
产品
解决方案
定价
更多

带赋值运算符的表达式求值顺序问题:为何代码运行结果z=20而非预期19

代码结果偏差的底层原因解析

涉及的原代码

#include <iostream>
using namespace std;
int main() {
    int y=3;
    int z = (--y) + (y=10);
    printf("%d \n", z);
}

核心问题本质

这段代码属于C++标准明确规定的未定义行为,不存在唯一的正确输出,你推导的19和实际得到的20,都是不同编译器自由实现的结果,不属于逻辑推导错误。

预期输出19的推导前提

你默认遵守的规则是「加法运算符先计算右操作数,再计算左操作数」,推导流程为:

  • 初始y赋值为3
  • 先执行右操作数y=10,将y的值修改为10
  • 再执行左操作数--y,将y的值减1得到9
  • 最终加法结果为9 + 10 = 19
    但这个求值顺序本身没有标准强制依据,不是编译器必须遵守的规则。

实际输出20的生成逻辑

对应编译器的实现属于未定义行为允许的自由优化,常见逻辑为:

  • 先执行右操作数y=10的赋值,y被修改为10
  • 计算左操作数时,编译器直接读取当前y的值10作为--y的返回值,甚至直接省略了前置自减的副作用(也就是没有实际执行y减1的操作)
  • 最终加法结果为10 + 10 = 20

底层语法规则说明

核心原因是C++的序列点规则:

C++标准明确规定:当对同一标量对象的两个未排序的副作用没有被序列点隔开时,程序行为是未定义的。

  • 在C++17标准之前,若同一表达式中存在多个针对同一内存位置(这里是变量y的存储单元)的副作用(--y会修改y,y=10也会修改y),且两个副作用之间没有序列点隔开,就属于未定义行为。
  • 加法运算符+本身不会引入序列点,也没有规定左右操作数的求值顺序,编译器可以自由重排操作、甚至省略部分合法的操作步骤,标准对这类未定义行为没有任何约束要求。
  • C++17虽对部分运算符的求值顺序做了强制规定,但加法运算符的左右操作数求值顺序仍未明确,这种写法依然会触发未定义行为,工程中应避免编写这类存在歧义的代码。

内容的提问来源于stack exchange,提问作者Quang Thinh Ha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 19:36:02