这是很多初级C/C++程序员最容易碰到的一个问题
这里来给大家简明摘要的给大家讲解一下:
i++
i++是后递增
有如下语句:
int i = 0;
printf("%d,",i++);
在打印输出时会发现是0,上面也说了i++是后递增其意思就是在一条指令执行完成之后才会去对i这个变量进行递增
printf("%d",i++);的执行流程如下:
先printf打印i的值,在打印完成之后也就是语句结束时对i进行递增
我们可以做个试验:
int i = 0;
printf("%d,",i++);
printf("%d",i);
打印结果:0,1
也就是证明了上面说的后递增会在语句结束时对变量进行递增
我们来看一下汇编代码(如果没有学过汇编的可以直接跳过这一步骤)
printf("%d", i++);
00C91C79 mov eax,dword ptr [i]
00C91C7F mov dword ptr [ebp-1C4h],eax
00C91C85 mov ecx,dword ptr [i]
00C91C8B add ecx,1
00C91C8E mov dword ptr [i],ecx
00C91C94 mov esi,esp
00C91C96 mov edx,dword ptr [ebp-1C4h]
00C91C9C push edx
00C91C9D push 0C96858h
00C91CA2 call dword ptr ds:[0C9A120h]
00C91CA8 add esp,8
00C91CAB cmp esi,esp
00C91CAD call __RTC_CheckEsp (0C9115Eh)
dword(双字类型四字节) ptr(指针指向地址)
dword ptr [i]指令意思就是指向一个四字节的i地址
mov eax,dword ptr [i]
此时将eax寄存器中的值写入到栈低指针-1C4h的地址当中去,
mov dword ptr [ebp-1C4h],eax
通过mov和ptr指令的作用将位于内存中i的值写入的累加器中(EAX寄存器,ALU运算单元所使用的寄存器)
mov ecx,dword ptr [i]
最后在对暂存器里的值进行递增1
add ecx,1
然后写入到里面去
00C91C8E mov dword ptr [i],ecx
最后这一段代码是调用printf函数的代码并将要打印输出的值传递进去
00C91C96 mov edx,dword ptr [ebp-1C4h]
00C91C9C push edx
00C91C9D push 0C96858h
00C91CA2 call dword ptr ds:[0C9A120h]
我们来分析一下
mov edx,dword ptr [ebp-1C4h]
这行代码的作用是将栈中栈低指针-1C4h的值写入到edx通用寄存器当中,注意此时低指针-1C4h的值是0,在最开始的汇编代码处也说过,在一开始编译器就将i的值写入到该内存中去了:
mov eax,dword ptr [i]
mov dword ptr [ebp-1C4h],eax
期间该内存值没有任何变化
然后压入新值到栈中
push edx
push 0C96858h
调用printf函数并打印edx寄存器的值,每次调用printf,printf函数都会自动从edx寄存器中读取要打印的数据
call dword ptr ds:[0C9A120h]
从上面的代码可以的值printf的入口地址位于内存中的0C9A120h当中,所以通过上面几行汇编代码的分析也就得知为什么i++在打印时不是递增后的值了
注意printf每次编译运行时地址都会发生改变,printf函数在编译期间会被链接到文件当中并分配一个新的文件偏移内存映射地址!
下面在说一些最后的几行汇编代码吧
给栈顶指针递增8个字节
add esp,8
cmp指令是减法操作,操作之后会设置标志位寄存器所以也就是判断指令,注意进行减法运算后并不会对两个寄存器里的值产生任何影响,结果会存放到通用寄存器当中,并根据通用寄存器的值来设置标志位!
判断变址寄存器与esp地址
cmp esi,esp
后面的汇编指令中没有任何判断标志位的指令,所以这里就只是调用一下cmp指令,并没有做任何判断!
call __RTC_CheckEsp (0C9115Eh)
__RTC_CheckEsp函数是检查某内存缓冲区是否溢出的
调用此函数检查0C9115Eh内存缓冲区是否溢出!
++i就非常简单了
int i = 0;
printf("%d",++i);
打印结果:1
++i为前递增,也就是先对其进行递增后使用printf打印输出
汇编代码:
013A1CB2 mov eax,dword ptr [i]
013A1CB8 add eax,1
013A1CBB mov dword ptr [i],eax
013A1CC1 mov esi,esp
013A1CC3 mov ecx,dword ptr [i]
013A1CC9 push ecx
013A1CCA push 0C96858h
013A1CCF call dword ptr ds:[0C9A120h]
013A1CD5 add esp,8
013A1CD8 cmp esi,esp
013A1CDA call __RTC_CheckEsp (0C9115Eh)
这两行代码可以看出来,直接将i的值写入到eax寄存器中,并直接递增1,也不写入到ebp-1C4h栈地址中临时存储了
mov eax,dword ptr [i]
add eax,1
最后直接将i的值写入到ecx寄存器中,并把ecx寄存器的值压入栈,然后调用printf函数打印输出
mov ecx,dword ptr [i]
push ecx
push 0C96858h
call dword ptr ds:[0C9A120h]
从汇编代码可以分析出,++i要快于i++,因为++i无需写入到ebp-1C4h栈地址中存储数据,而是直接对i本身内存地址进行操作!