C/C++中的函数参数传递机制  

一、 函数参数传递机制的基本理论
  函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。
  值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
  引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的
实参变量。

二、 C语言中的函数参数传递机制

  在C语言中,值传递是唯一可用的参数传递机制。但是据笔者所知,由于受指针变量作为函数参数的影响,有许多朋友还认为这种情况是引用传递。这是错误的。请看下面的代码:
int swap(int *x, int *y)
{
int temp;
temp = *x; *x = *y; *y = temp;
return temp;
}
void main()
{
int a = 1, b = 2;
int *p1 = &a;
int *p2 = &b;
swap(p1, p2)
}
  函数swap以两个指针变量作为参数,当main()调用swap时,是以值传递的方式将指针变量p1、p2的值(也就是变量a、b的地址)放在了swap在堆栈中为形式参数x、y开辟的内存单元中。这一点从以下的汇编代码可以看出(注释是笔者加的):
22: void main()
23: {
……
……
13: int a = 1, b = 2;
00401088 mov dword ptr [ebp-4],1
0040108F mov dword ptr [ebp-8],2
14: int *p1 = &a;
00401096 lea eax,[ebp-4]
00401099 mov dword ptr [ebp-0Ch],eax
15: int *p2 = &b;
0040109C lea ecx,[ebp-8]
0040109F mov dword ptr [ebp-10h],ecx
16: swap(p1, p2);
004010A2 mov edx,dword ptr [ebp-10h] ;参数p2的值进栈
004010A5 push edx
004010A6 mov eax,dword ptr [ebp-0Ch] ;参数p1的值进栈
004010A9 push eax
004010AA call @ILT+15(swap) (00401014) ;调用swap函数
004010AF add esp,8 ;清理堆栈中的参数
17: }
  阅读上述代码要注意,INTEL80x86系列的CPU对堆栈的处理是向下生成,即从高地址单元向低地址单元生成。从上面的汇编代码可知,main()在调用swap之前,先将实参的值按从右至左的顺序压栈,即先p2进栈,再p1进栈。调用结束之后,主调函数main()负责清理堆栈中的参数。Swap 将使用这些进入堆栈的变量值。下面是swap函
数的汇编代码:
14: void swap(int *x, int *y)
15: {
00401030 push ebp
00401031 mov ebp,esp ;ebp指向栈顶
……
……
16: int temp;
17: temp = *x;
4: int temp;
5: temp = *x;
00401048 mov eax,dword ptr [ebp+8] ;操作已存放在堆栈中的p1,将p1置
; 入eax
0040104B mov ecx,dword ptr [eax] ;通过寄存器间址将*p1置入ecx
0040104D mov dword ptr [ebp-4],ecx;经由ecx将*p1置入temp变量的内
;存单元。以下类似
6: *x = *y;
00401050 mov edx,dword ptr [ebp+8]
00401053 mov eax,dword ptr [ebp+0Ch]
00401056 mov ecx,dword ptr [eax]
00401058 mov dword ptr [edx],ecx
7: *y = temp;
0040105A mov edx,dword ptr [ebp+0Ch]
0040105D mov eax,dword ptr [ebp-4]
00401060 mov dword ptr [edx],eax
8: return temp;
00401062 mov eax,dword ptr [ebp-4]
9: }
  由上述汇编代码基本上说明了C语言中值传递的原理,只不过传递的是指针的值而已。本文后面还要论述使用引用传递的swap函数。从这些汇编代码分析,这里我们可以得到以下几点:
  1. 进程的堆栈存储区是主调函数和被调函数进行通信的主要区域。
  2. C语言中参数是从右向左进栈的。
  3. 被调函数使用的堆栈区域结构为:
    局部变量(如temp)
    返回地址
    函数参数
    低地址
    高地址
  4. 由主调函数在调用后清理堆栈。
  5. 函数的返回值一般是放在寄存器中的。
  这里尚需补充说明几点:一是参数进栈的方式。对于内部类型,由于编译器知道各类型变量使用的内存大小故直接使用push指令;对于自定义的类型(如structure),采用从源地址向目的(堆栈区)地址进行字节传送的方式入栈。二是函数返回值为什么一般放在寄存器中,这主要是为了支持中断;如果放在堆栈中有可能因为中断而被覆盖。三是函数的返回值如果很大,则从堆栈向存放返回值的地址单元(由主调函数在调用前将此地址压栈提供给被调函数)进行字节传送,以达到返回的目的。对于第二和第三点,《Thinking in C++》一书在第10章有比较好的阐述。四是一个显而易见的结论,如果在被调函数中返回局部变量的地址是毫无意义的;因为局部变量存于堆栈中,调用结束后堆栈将被清理,这些地址就变得无效了。

三、 C++语言中的函数参数传递机制
  C++既有C的值传递又有引用传递。在值传递上与C一致,这里着重说明引用传递。如本文前面所述,引用传递就是传递变量的地址到被调函数使用的堆栈中。在C++中声明引用传递要使用"&"符号,而调用时则不用。下面的代码是使用引用传递的swap2函数和main函数:
int& swap2(int& x, int& y)
{
int temp;
temp = x;
x = y;
y = temp;
return x;
}

void main()
{
int a = 1, b = 2;
swap2(a, b);
}
  此时函数swap2将接受两个整型变量的地址,同时返回一个其中的一个。而从main函数中对swap2的调用swap2(a, b)则看不出是否使用引用传递,是否使用引用传递,是由swap2函数的定义决定的。以下是main函数的汇编代码:
11: void main()
12: {
……
……
13: int a = 1, b = 2;
00401088 mov dword ptr [ebp-4],

C/C++中的函数参数传递机制 作者:杨宁 发布时间:2000/11/30相关推荐

  1. jQuery 中的事件参数传递机制

    jQuery 中的事件参数传递机制 jQuery事件参数传递模型: 注:trigger 不能与 bind 的原生函数一样,使用同样的参数传递形式: 参数传递一: $(document).ready(f ...

  2. Python: 函数参数传递机制

    Python: 函数参数传递机制 Python函数参数由实参传递给形参的过程,是由参数传递机制来控制的,根据实际参数类型不同,函数参数传递方式分为值传递和引用传递(又称为地址传递). 值传递机制 所谓 ...

  3. php ob 缓存,php中ob函数缓冲机制深入理解

    下面就php中ob函数缓冲机制通过文字说明加代码分析的形式给大家展示如下: 对于一个刚刚入门的php程序员来说,php缓冲区是几乎透明的.在他们心目中,一个echo print_r 函数,数据便会'嗖 ...

  4. C/C++和python中的函数参数传递

    目录 一.C/C++中的函数参数传递 二.python中函数的参数传递问题 一.C/C++中的函数参数传递 1.C/C++中的普通参数传递和指针参数传递本质上都是值传递,只不过当使用指针接收实参传递的 ...

  5. python参数传递_python中的*和**参数传递机制

    python的参数传递机制具有值传递(int.float等值数据类型)和引用传递(以字典.列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如 ...

  6. 两种参数类型_深入理解Java中方法的参数传递机制

    形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. ...

  7. python 函数参数传递机制_Python函数参数传递机制(超级详细)

    Python中,函数参数由实参传递给形参的过程,是由参数传递机制来控制的.通过学习<Python函数值传递和引用传递>一节我们知道,根据实际参数的类型不同,函数参数的传递方式分为值传递和引 ...

  8. (转载)Python函数参数传递机制(超级详细)

    Python中,函数参数由实参传递给形参的过程,是由参数传递机制来控制的.根据实际参数的类型不同,函数参数的传递方式分为值传递和引用传递(又称为地址传递),本节将对这两种传递机制做深度剖析. Pyth ...

  9. python和nodejs数据传递_python中的*和**参数传递机制

    python的参数传递机制具有值传递(int.float等值数据类型)和引用传递(以字典.列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如 ...

  10. java中gettext方法_深入理解Java中方法的参数传递机制

    形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. ...

最新文章

  1. milp的matlab的案例代码_matlab30个案例分析案例6代码
  2. JavaScript规范
  3. 64位汇编之linux系统调用
  4. 程序员面试题精选100题(33)-在O(1)时间删除链表结点[数据结构]
  5. 深入分析JVM逃逸分析对性能的影响
  6. python每隔半个小时执行一次_一篇文章教你用Python抓取微博评论
  7. 随机加解密java_JAVA随机数生成 Math.random和java.util.Random使用简介
  8. 计算机一级查询证书编号,如何查询计算机一级证书编号
  9. [4G5G专题-9]:前传接口 CPRI与OBSAI的那些事
  10. 微信小程序关于map地图
  11. WeNet语音识别实战
  12. 店盈通:新品牌如何活得更好、活得更久
  13. 怎么在win下装python requests
  14. dp动态规划刷题总结
  15. iText7 解套 (一) 原生方法输出带斜线表格
  16. php公众号提现功能,公众号赞赏提现
  17. 腾讯云CVM云服务器1M宽带能干嘛?1M宽带支撑多少人在线?
  18. 赛车编程用c语言,钟神赛车 (C++代码)自己AC了都觉得搞笑
  19. 计算机科学的发展及其介绍,计算机科学与技术专业发展历史介绍
  20. 解决Win8为硬件保留了XXXg内存 问题

热门文章

  1. React基础之事件机制
  2. java-php-python-ssm抑郁症患者博客交流平台计算机毕业设计
  3. CentOS8 dnf软件包管理配置
  4. Kali 实现ARP断网攻击_arp断网攻击_arp欺骗
  5. 链路聚合、Trunk、端口绑定和捆绑简析
  6. 黑冰客防骗子—常见网络骗子骗术防御要点zxtd
  7. Simulink提速方式
  8. 【font-spider】网页中引用字体文件过大的解决办法,网页字体文件压缩
  9. 阅读文献Performance Gains in V2X Experiments Using Distributed Simulation in the Veins Framework
  10. python常用语音识别库_python语音识别