经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
a++与++a,谈谈C++的参数传递
来源:cnblogs  作者:小帆帆耍大牌  时间:2019/10/8 9:32:50  对本文有异议

先看一段代码:

  1. #include<iostream>
  2. using namespace std;
  3. void func(int a, int b)
  4. {
  5. cout << a << " " << b << endl;
  6. }
  7. int main()
  8. {
  9. int a = 0;
  10. func(a++, ++a);
  11. return 0;
  12. }

由于C++是从右向左入栈(与编译器的调用约定有关,不是C++标准的规定),所以刚看到代码的时候,我以为结果会是“1 1”(先将++a入栈,再将a++入栈),然而事实是: 。这是在VS上面运行的,在g++上也是一样的结果。幸好VS还可以查看汇编代码。


由于在VS上有十分方便的反汇编工具,所以接下来说的东西都基于VS2019自带的反汇编。
设置断点并调试,便可以打开反汇编窗口:



下面这段就是在调用func函数时的汇编代码:

  1. mov eax,dword ptr [a]
  2. add eax,1
  3. mov dword ptr [a],eax //这三行指令将a+1
  4. mov ecx,dword ptr [a]
  5. mov dword ptr [ebp-0D0h],ecx //这两行指令将a的值存储到一个临时地址(寄存器间接寻址)中
  6. mov edx,dword ptr [a]
  7. add edx,1
  8. mov dword ptr [a],edx /这三行指令又将a+1
  9. mov eax,dword ptr [a]
  10. push eax //这两行指令将a压入栈
  11. mov ecx,dword ptr [ebp-0D0h]
  12. push ecx //这两行指令将刚刚存储的临时地址的值压入栈
  13. call func (0A312E9h) //调用func函数
  14. add esp,8 //esp为栈指针寄存器

如果将代码改成

func(++a, ++a);

会是什么结果呢?答案是

  1. mov eax,dword ptr [a]
  2. add eax,1
  3. mov dword ptr [a],eax //这三行指令将a+1
  4. mov ecx,dword ptr [a]
  5. add ecx,1
  6. mov dword ptr [a],ecx //这三行指令将a+1
  7. mov edx,dword ptr [a]
  8. push edx //这两行指令将a压入栈
  9. mov eax,dword ptr [a]
  10. push eax //这两行指令将a压入栈
  11. call func (09912E9h)
  12. add esp,8

可以看到,将a++改成++a之后,指令少了将a的值保存起来的步骤,并且由于并非在读取参数时就压入栈,而是在所有参数的表达式执行完之后才压入,所以最后压入参数栈的都是最后的变量a。
那么结合汇编代码就不难理解文章开头为什么是“1 2”了,基本就是这样的区别(注意:读取参数和执行参数的表达式时也是从右往左的)

在调用函数的时候,参数要避免使用自增和自减,避免出现混乱。


文章为作者结合个人理解编写,可能会有错漏的地方,如有错误,敬请指正。

原文链接:http://www.cnblogs.com/fancyxie/p/11618369.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号