Chinaunix首页 | 论坛 | 博客
  • 博客访问: 166582
  • 博文数量: 18
  • 博客积分: 299
  • 博客等级: 二等列兵
  • 技术积分: 731
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-19 00:39
文章分类

全部博文(18)

文章存档

2013年(7)

2012年(11)

分类: C/C++

2012-03-29 17:21:46

本文为原创,纯属本人理解,如有错误,请不吝指出。

最近遇到一个问题:
我写了一个函数,函数当中调用f(a),char a是在这个函数里面仅仅用作计算的,并不会改变a的值,这时有另外一个人说必须要f(&a)才更好。为了深入研究这个问题,我写了一些实验函数验证了一下。
环境在VC++ 6.0当中实验。 

点击(此处)折叠或打开

  1. void f(double a)
  2. {
  3. }
  4. void f2(double a[222])
  5. {
  6. }
  7. void f1(double* a)
  8. {
  9. }
  10. int main()
  11. {
  12.     double a;
  13.     double b;
  14.     double c[200];

  15.     f(a);
  16.     f1(&b);
  17.     f2(c);
  18.     return 0;
  19. }
文中列举了a, b,c3中传参的方式,查看一下汇编下面的运行情况

点击(此处)折叠或打开

  1. 19: f(a);
  2. 0040131E mov eax,dword ptr [ebp-4]
  3. 00401321 push eax
  4. 00401322 mov ecx,dword ptr [ebp-8]
  5. 00401325 push ecx
  6. 00401326 call @ILT+5(f) (0040100a)
  7. 0040132B add esp,8
上面的代码是指的是double a传参数的具体情况,首先把a的2个字节的内容放入eax寄存器当中,然后压入函数栈,然后把后2个直接的内容放入ecx寄存器当中,然后压入函数栈。

点击(此处)折叠或打开

  1. 20: f1(&b);
  2. 0040132E lea edx,[ebp-10h]
  3. 00401331 push edx
  4. 00401332 call @ILT+0(f1) (00401005)
  5. 00401337 add esp,4
上面的代码指的是double b;的具体的传参数情况,将b的地址取出,存放到edx这个寄存器当中,然后压栈。


点击(此处)折叠或打开

  1. 21: f2(c);
  2. 0040133A lea eax,[ebp-650h]
  3. 00401340 push eax
  4. 00401341 call @ILT+25(f2) (0040101e)
  5. 00401346 add esp,4
上面的代码指的是 double c[200]; 的具体的传参数情况,将c的地址取出,存放到edx这个寄存器当中,然后压栈。

第三种情况虽然c是个数组,里面有200个double类型的变量,但是传到函数当中的时候过程和第二种情况是一样的。
对于第一种情况,由于现在是double类型的变量,8个直接的,于是4个字节的寄存器无法一次存入,因此压栈的开销要大于第二,第三种情况。
但是如果第一种情况是一个char a类型的变量的话,那么这个压栈的过程就跟第2,第三种情况开销一致了。
所以说一开始的问题调用f(a)或者是f(&a)完全是可以的,另外,考虑当程序的可读性和安全性,个人还是推荐写f(a)比较好,这样a不会在函数里由于什么原因被修改掉。

阅读(1943) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:如何成功调用JNI的实例

给主人留下些什么吧!~~

bough222012-09-12 10:50:52

如果要研究传参方式,建议写一个多参数的函数试试,最好参数多于4个,参数形式也要多样化,比如有数组,指针等等,用arm和x86的处理器分别反汇编,对比学习,效果比较好。