函数调用过程详解

转载 2012年03月27日 14:22:40
(2010-10-08 08:45:01)
标签:

杂谈

 
函数调用过程详解
函数调用过程详解

    问题出现的原因:在函数调用时,系统会产生一个栈,会进行函数参数压栈,函数名压栈,局部变量压栈,返回地址压栈。然后再栈里面会产生一个实参的副本,函数体内对a的修改,只是针对栈内副本的修改,函数调用结束后,栈要清空,在栈里面的操作全部无效(除非把栈里面的东西返回给实参),没有对实参造成任何影响。所结果仍为5。
    如果想得到正确的结果除非实参和形参指向同一块地方,就是说,如果改成传地址的话,虽然函数调用的时候,在栈里面给指针分配了空间(指针也是要有空间存储它的,不像引用&),但是指针指向的地址就是实参所在的地址,对形参的修改,也就是对实参的修改。结果皆大欢喜!

函数调用过程详解
函数调用过程详解

     解释:结果为什么不是我们期望的那样呢?而且发生了运行时异常!
    在函数调用时候,OS为我们产生一个栈,在栈中为指针变量分配了空间,函数体内未执行前,形参和实参指向同一块内存空间(如图FF5C),(最根本的原因是p只是存了一份str的副本,相当于值传递)然后函数体内执行了malloc操作后(malloc操作执行的过程是,先在堆里面申请一块内存空间,完了再把这块堆空间的首地址返回给调用者),于是p指向了堆空间的地址,也就是说把申请的堆空间地址返回给了在栈里面的p,而不是返回给了实参str,实参str完全不知道p的改变,函数返回时,会撤销栈里面的所有东西(除非把结果返回给实参),p被释放了当然p存的堆地址也消失了,于是存在着内存泄露的风险(没人去释放这块内存,即使想释放也不知道这块内存地址)。
    解决的办法有多种,例如设置返回值...这里选取最经典的一种:
    函数调用过程详解
    
    可也把上面的情形设想成这样:本来是想丢修改&str这块内存空间的内容(只不过&str的内容比较特殊是个地址),但是因为是值传递,形参只是对实参的一份拷贝(浅拷贝),对形参的任何修改没有对实参有任何影响。如果想有影响怎么办?让实参和形参都指向&str,对形参的修改也就是对实参的修改。但是参数传递的时候怎么办呢,如果想修改&str的内容,必须把&str地址赋形参,但是str本身是个指针,于是形参只能是二级指针了。
   一句话,如果想让函数对实参的内容进行修改,那么必须把实参的地址付给形参,让实参和形参指向同一块内存。如果实参本事是个指针,那么形参就应该是指针的指针,实参是指针的指针,形参就应该是(指针的指针的指针)

相关文章推荐

函数调用过程详解

当调用者比如h调用某个函数f时,从编译器或者汇编语言角度来看,主要分以下几个步骤进行: h将实参按照从右向左的顺序一个个压入stack中。 执行一个转移指令call f f执行完函数体后...

24张图详解 寄存器 EBP ESP 在函数调用过程中的作用

c.cpp int g_x=3            /* 因为g_x是全局变量所以编译的时候,它已经被编译到了  数据段中  故:代码段没有它 */ int fun_a...
  • okayu
  • okayu
  • 2017-06-12 13:31
  • 92

函数调用过程(详解)

原文: http://www.cnblogs.com/biyeymyhjob/archive/2012/07/20/2601204.html#include int func(int param1 ...

arm函数调用和返回过程详解

arm函数调用和返回过程详解ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递0x00 ...

C++函数调用过程深入分析

  • 2011-08-11 20:39
  • 748KB
  • 下载

oracle函数调用存储过程

  • 2012-06-26 11:01
  • 47KB
  • 下载

深入理解C语言----函数调用过程浅析

读了韩宏老师的《老码识途》第一章,忍不住自己动手试一下,利用反汇编来查看函数调用过程 #include typedef struct { int i1; int i2; int i3 }my...

read()函数调用过程剖析

  • 2012-03-29 21:20
  • 142KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)