C/C++中作为函数参数的 i++ 与 ++i
来源:互联网 发布:淘宝网页设计的评价 编辑:程序博客网 时间:2024/06/03 17:18
平时写代码时,经常会遇到自加自减运算,我们知道这种自加自减运算有两种形式,一种就是我们所谓的前置++(或- -)(例如:++i),另一种是后置++(或- -)(例如: i++)。那么这两者的区别是什么呢?
为简单起见,我们以 i++ 和++i 为例,说明两者的区别: i++ 是先取 i 的值,再进行自加运算;而++i是先做自加运算,再取 i 的值。我们来看看下面的例子:
int i = 5; int a = ++ i;
根据上面的分析,容易知道 a = 6,因为这里是前置++, 先做加1运算再取值。将上面代码的第二句换成 int a = i ++, 此时的 i 值就是5。这些理解起来都很简单,我们来分析下面的例子:
int i = 0; printf ("%d, %d, %d\n",i ++, --i, i ++);
我们知道函数传参顺序是自右向左,那么最右边是i++, 根据前置++的特性,先取 i 的值为0,即压栈的参数值为0,再自加1得到 i = 1,;再看从右到左第二个参数,是前置- -,先做自减运算得到i = 0,取i 的值压栈,即此时压栈的也是0;最后看从右到左第三个参数,是后置++,先取 i 的值,即i = 0 进行压栈。这样分析下来我们打印出来的应该是:0, 0, 0。但是运行后我们却发现打印结果为: 0, 1, 0。为什么会出现这样的结果?这就要看在函数调用时,压栈参数的值到底是多少。下面我们从汇编的角度来分析这个结果,先来看printf那一行代码的汇编码:
printf (“%d, %d, %d\n”,i ++, –i, i ++);
我们分析从右向左第一个参数: i++
下面两个指令是将i的值0放在临时地址ebp-0D0h中(这里我们将其理解为临时量)
(即先保存值)
mov eax,dword ptr [i]
mov dword ptr [ebp-0D0h],eax
下面三条指令是从内存中取出i 的值,做+1运算后,将 i 的值 1 放入内存
(再进行自加运算)
mov ecx,dword ptr [i]
add ecx,1
mov dword ptr [i],ecx
第二个参数:- - i
下面三条指令是从内存中取出i的值1,进行自减运算得到i = 0,将0放入i的内存
(先进行自减运算)
mov edx,dword ptr [i]
sub edx,1
mov dword ptr [i],edx
第三个参数: i ++
下面两条指令是将 i 的值0放入临时地址ebp-0D4h中
(先保存i的值0)
mov eax,dword ptr [i]
mov dword ptr [ebp-0D4h],eax
下面三条指令是做自加运算,得到i的值1放入i的内存(注意此时i的内存中的值为1)
(再做自加运算)
mov ecx,dword ptr [i]
add ecx,1
mov dword ptr [i],ecx
这里才是重点,前面都是在计算或保存参数的值,我们来看看压栈的是什么值:
根据形参压栈顺序,第一个压栈的应该是最右边的i++,我们看到这里压栈的是临时量[ebp-0D0h]的值,即0,第二个压栈的是- -i,这里是从内存中取的值,即1,进行压栈,第三个压栈的是最左边的i ++,压栈的是临时量[ebp-0D4h]里面的值,即0。这样,我们就不难理解为什么打印结果是0, 1, 0,而不是我们所想的0, 0, 0.
mov edx,dword ptr [ebp-0D0h]
push edx
mov eax,dword ptr [i]
push eax
mov ecx,dword ptr [ebp-0D4h]
push ecx
从这个例子中,我们容易得到:当i ++ 和 ++i (当然也包括自减运算)作为函数实参时,编译器对两者取值的处理是不同的,是i++时,编译器是从临时量中取值的,而++i是从i的内存中取值的。所以,当参数列表中有多个前置++(或- -)时,他们最终打印的值是一样的,都是最终内存中存储的那个值。
- C/C++中作为函数参数的 i++ 与 ++i
- c,c++语言中 i++ 与 ++i
- 在C语言中 i++与++i的区别
- c语言中i++与++i的使用技巧
- C中&与I的使用
- c/c++ 中毫无意义的 i+++++i
- c语言中i++,++i的计算
- C语言中指针变量作为函数参数和一般变量作为函数参数的区别
- C语言中函数作为参数的问题
- C语言中数组作为函数参数的问题
- C语言中“指针”作为“函数参数”时的注意事项
- c语言中指针变量作为函数的参数
- c语言函数---I
- i++和++i是怎么用的?它们作为函数参数时的使用举例
- C标准I/O库函数与无缓存的I/O函数
- C语言优先级和(i++)+(i++)与(++i)+(++i)
- 【C++】指针作为函数的参数
- Objective-c - block作为函数的参数
- 2016-2017 ACM-ICPC, NEERC, Central Subregional Contest
- lucene的IndexReader的初始化过程
- MFC——VS中MSComm串口控件的导入和注意事项
- FreeSWITCH学习笔记 第一场 第二个镜头 视频通话配置
- CAD怎么批量转成PDF格式
- C/C++中作为函数参数的 i++ 与 ++i
- Spark的学习笔记
- Nginx Sticky的使用及踩过的坑(nginx-sticky-module)
- 美女大头的通达OA2017最新版本的全年托管服务
- 设计模式之外观模式
- java中json字符串的拼接
- nginx 初探
- Blog11@linux文件系统间的传输、归档及压缩
- java的对称加密算法 AES -----加密和解密