You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

序列点、函数调用与未定义行为:为何i+++i++未定义而f(i)+f(i)却不是?

为什么i++ + i++是未定义行为而f(i)+f(i)不是?

示例代码与编译命令

代码文件main.cpp

const int& f(int& i ) { return (++i);}
int main(){
   int i = 10;
   int a = i++ + i++; // 未定义行为
   int b = f(i) + f(i); // 无未定义行为
}

编译命令

$ g++ main.cpp -Wsequence-point

核心原因:序列点(顺序规则)的差异

1. int a = i++ + i++; 触发未定义行为

C标准明确规定:如果在**没有序列点(C11及以后为“顺序规则”)分隔**的情况下,对同一个对象同时进行多次修改,或者修改与读取操作重叠,就会产生未定义行为。

i++是后置自增操作,逻辑是先读取i的当前值用于表达式计算,再将i的值加1。在i++ + i++这个表达式里,两个i++操作之间没有任何序列点:编译器既可以选择先读取两次i的值再执行两次自增,也可以先执行一次自增再读取第二次i的值——标准没有规定具体顺序,不同编译器甚至同一编译器的不同优化等级都可能给出不同结果,这就是典型的未定义行为。

2. int b = f(i) + f(i); 无未定义行为

函数调用是C++中明确的序列点来源:每个函数调用的执行过程中,函数内部的所有副作用(比如++i对i的修改)都会在函数返回前完全完成,函数调用结束就是一个序列点。

对于f(i)+f(i)来说,不管编译器选择先执行左边的f(i)还是右边的f(i),每个f(i)调用内部的++i操作都会在该函数返回前完成,不会出现“同一个对象在无序列点下被多次修改”的情况。无论调用顺序如何,最终的计算结果都是确定的(两次自增后的数值相加),因此不存在未定义行为。

内容的提问来源于stack exchange,提问作者Vivek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:15:42