i++ 和 ++i 的区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(void) {

int i;

i = 0;
printf("i++ = %d\n", i++);
printf("i = %d\n", i);

i = 0;
printf("++i = %d\n", ++i);
printf("i = %d\n", i);

return 0;
}

输出结果:

1
2
3
4
i++ = 0
i = 1
++i = 1
i = 1

不管是 i++ 还是 ++i 最终都会让 i 产生副作用,即都会使得 i 在原来的基础上 加 1。二者的区别在于 ++i 的值 代表 i+1,而 i++ 的值 代表 i。即 ++i 会立即产生自增的效果,而 i++ 不会立即产生自增的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
i++ 对应的汇编代码

0042186C mov eax,dword ptr [i] ; 将变量 i 的值加载到 eax 寄存器中
0042186F mov dword ptr [ebp-0D0h],eax ; 将 eax 中的值(即 i 的当前值)存储到内存(临时变量)
00421875 mov ecx,dword ptr [i] ; 再次加载 i 的值到 ecx 寄存器
00421878 add ecx,1 ; 对 ecx 中的 i 进行递增操作
0042187B mov dword ptr [i],ecx ; 将递增后的值存储回 i
0042187E mov edx,dword ptr [ebp-0D0h] ; 将最初保存的 i 的值加载到 edx
00421884 push edx ; 将最初的 i 值压入堆栈,用于 printf 输出
00421885 push offset string "%lld\n" ; 压入字符串格式化参数
0042188A call _printf ; 调用 printf 函数
0042188F add esp,8 ; 调整堆栈指针


++i 对应的汇编代码

004218AA mov eax,dword ptr [i] ; 将变量 i 的值加载到 eax 寄存器中
004218AD add eax,1 ; 对 eax 中的 i 进行递增操作
004218B0 mov dword ptr [i],eax ; 将递增后的值存储回 i
004218B3 mov ecx,dword ptr [i] ; 再次加载递增后的 i 到 ecx 寄存器
004218B6 push ecx ; 将递增后的 i 值压入堆栈,用于 printf 输出
004218B7 push offset string "++i = %d\n" ; 压入字符串格式化参数
004218BC call _printf ; 调用 printf 函数
004218C1 add esp,8 ; 调整堆栈指针

解读:

从 ++i 的汇编代码可以看出是 先让 i 执行自增操作之后才打印 i 的值,所以打印结果为 1。

i++ 的汇编代码是把 i 最初的值转存到其他临时地址,并读取原始 i 的值进行自加后放到其他寄存器,然后再把之前存储到临时地址的 i 的数据用于输出,所以打印结果为 0。

总结:

i++ 先使用 i 的原值,再递增。这就需要在递增之前保存 i 的原值,以便在后续操作中使用。

++i 先递增 i,然后使用递增后的值。这个过程更简单,不需要保存原值,因为递增操作已经完成。