Chuangxin 函数调用过程详解 【面】

来源:互联网 发布:alias软件 汉化版 编辑:程序博客网 时间:2024/05/02 06:10

出处链接 : http://blog.sina.com.cn/s/blog_60e96a410100n1gl.html


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


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

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


原创粉丝点击