前置自增++i先增后用,赋值时i和j同为6;后置自增i++先用后增,赋值后j为5、i变为6;二者语义不同,易混淆。

前置自增 ++i 在赋值中立即生效
前置自增会先修改变量值,再参与后续表达式计算。赋值语句右边的 ++i 意味着:先让 i 加 1,然后把加完后的值拿去赋给左边变量。
常见错误是以为它和后置一样“先用后改”——其实它根本没“先用”这一步。
- 如果
i = 5,执行j = ++i后,i和j都是6 - 在函数调用中如
foo(++i),传入的是递增后的值 - 性能上无差别,但语义更直白:你要的就是“改完再用”
后置自增 i++ 在赋值中返回旧值
后置自增会先返回当前值,再执行加 1。赋值语句右边的 i++ 表示:先把此刻的 i 值交给左边变量,之后才让 i 自增。
这是最容易混淆的点——很多人调试时发现变量“好像没变”,其实是没意识到自增发生在赋值完成之后。
- 如果
i = 5,执行j = i++后,j是5,i变成6 - 在循环条件里写
while (i++ ,最后一次判断用的是i == 9,判断完才变成10 - 某些编译器对
i++会生成临时副本,虽现代优化通常消除,但语义上仍存在“读-存-改”三步
混合使用时顺序由运算符优先级和结合性决定
++ 的优先级高于赋值 =,所以 i++ = 5 是非法的(左值问题),而 a = i++ + ++j 是合法的,但结果依赖于求值顺序。
C/C++ 标准不规定 i++ + ++j 中两个子表达式的求值先后,只保证 i++ 返回旧值、++j 返回新值。因此这类写法属于未定义行为(UB)的高危区。
- 避免在同一表达式中多次修改同一变量,例如
i = i++ + i++ - 即使看似“确定”的写法如
k = i++ + i,C++17 起也明确为未定义行为 - Java/C# 等语言规定从左到右求值,但依然不建议依赖——可读性差且易迁移出错
调试时怎么一眼看出哪个在先执行
最直接的办法是拆开写,用临时变量显式暴露步骤。比如把 arr[i++] = x 改成:
arr[i] = x; i = i + 1;
这样逻辑一目了然,也方便打断点观察每步的值。尤其在指针偏移、数组索引、状态机跳转等场景,强行展开能避开 90% 的边界错误。
- IDE 调试时,
i++的自增动作通常出现在该行“执行完毕后”,而非“取值瞬间” - 反汇编看
i++一般对应mov+inc两指令,而++i是inc+mov - 静态分析工具(如 clang-tidy)会警告
i++在复杂表达式中的使用,不是因为它错,而是因为它容易被误读
实际写业务代码时,多数人真正卡住的不是“记不住规则”,而是看到别人写的 ptr = array[i++] 或 if (++count > limit) 时不敢动——怕改崩。记住一点:只要涉及自增/自减,就把它当成一个有副作用的独立动作,别让它藏在别的操作里。










