打印

C解析之五函数内幕

[复制链接]
1075|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
前言:关于函数,你不知到的那些事。
         C语言程序由多个函数组成,所有函数具有平行性,这意味着函数内部不能再定义函数。函数带来一大串问题,全局变量与局部变量是什么?它们的作用域与生存期有何不同?实际参数与形式参数又有何不同?为什么形式参数只有在被调用时才分配内存?返回值如何传递......在很多书上都可以找到答案,但...问题是,很少有书给予了让人满意的解释。

相关帖子

沙发
elecintop|  楼主 | 2014-3-29 20:02 | 只看该作者
void Swap(int a,int b){ //形参a,b
int temp;
temp=a;
a=b;
b=temp;
}
int main(){
int m=3;
int n=4;
Swap(m,n); //实参n,m
return 0;
}

使用特权

评论回复
板凳
elecintop|  楼主 | 2014-3-29 20:02 | 只看该作者

使用特权

评论回复
地板
elecintop|  楼主 | 2014-3-29 20:03 | 只看该作者
      1.main()调用前:
                         1.1压栈保存现场:   main将寄存器数据与机器状态压栈保存,当调用结束后,把这些压入栈的数据弹出就可以恢复main的运行,如图main指示的区域。
                         1.2参数入栈:   参数列表(m,n)按从左到右的顺序压入栈。
                         1.3返回地址入栈: 这是main()函数的下一条指令的地址,保存这个地址返回main后才知道该执行main的那条指令。

使用特权

评论回复
5
elecintop|  楼主 | 2014-3-29 20:03 | 只看该作者
2.Swap()被调用后:
                         2.1建立自己的堆栈:Swap()在如图Swap指示的区域建立自己的堆栈,这是每个函数运行的基础,局部变量等空间开辟均基于堆栈。
                         2.2建立局部变量:  Swap()在自己的栈上建立局部变量(包括函数定义的形式参数),栈在Swap指示的区域。局部变量存储位置问题,可参考【C解析之三】C语言的内存分配。

使用特权

评论回复
6
elecintop|  楼主 | 2014-3-29 20:04 | 只看该作者
2.3 Swap开始执行指令:函数运行的条件-堆栈建立完成后,Swap开始执行代码,完成其任务。  
2.4参数的访问 : Swap通过基地址+偏移量访问参数,如基地址+8是第一个参数m,基地址+12是第二个参数n的地址,并将其值赋给建立的局部变量a,b。

使用特权

评论回复
7
elecintop|  楼主 | 2014-3-29 20:04 | 只看该作者
3.Swap()执行完后:
                         3.1清理堆栈: Swap的任务已经完成,维持它运行的堆栈就没有存在的理由。
                         3.2返回值 : 如果有返回值,一般是将返回值放在寄存器中,main冲寄存器中获得返回值

使用特权

评论回复
8
elecintop|  楼主 | 2014-3-29 20:04 | 只看该作者
  4.main()恢复:
                        4.1返回地址 : 这条指令地址取出放入指令寄存器(处理器下一条处理的指令放在这个寄存器内)。
                         4.2弹栈恢复现场 :这个过程与1.1过程相反,恢复main调用前的环境。
                         4.3获取返回值 :如果有,一般到相应的寄存器内读取。
                至此,函数调用过程结束。现在分析这个过程,以期望可以找到问题的答案:

使用特权

评论回复
9
elecintop|  楼主 | 2014-3-29 20:05 | 只看该作者
1.全局变量与局部变量:全局变量不依赖任何函数,至始至终都存在,存储于静态区。2.1-2.1到3.1可以发现,局部变量时在函数被调用后才开始分配空间,并最终随函数一起消亡。
               2.生存期: 全局变量显然在整个程序过程都一直存在,而局部变量生于函数调用时,死于函数调用结束。
               3.实际参数与形式参数:通过1.2与1.2-1.4清楚的表明,形式参数是函数的局部变量,创建于函数调用时,并被参数赋值。赋值则意味着在被调用函数内的操作,将不会影响到实参m,n的值,Swap并不具有m,n互换的功能。(读者可以试试,实际上Swap(int &a,int &b)这样定义才具有交换的功能)。
               4.参数的传递 :参数的传递是通过地址偏移量完成,其中更多的细节参考C调用约定。
               5.返回值: 一般情况下,返回值通过寄存器传递,更多细节参考C调用约定。

使用特权

评论回复
10
yanyanyan168| | 2014-3-29 21:05 | 只看该作者
学习了!!

使用特权

评论回复
11
sgj245609615| | 2014-3-29 22:39 | 只看该作者
学习下

使用特权

评论回复
12
smilingangel| | 2014-4-20 21:55 | 只看该作者
elecintop 发表于 2014-3-29 20:03
1.main()调用前:
                         1.1压栈保存现场:   main将寄存器数据与机器状态压栈保 ...

这个过程讲解还是蛮好的,,我参考了,谢谢

使用特权

评论回复
13
monkeypony| | 2014-4-21 16:44 | 只看该作者
谢谢楼主分享!

使用特权

评论回复
14
angerbird| | 2014-4-21 22:22 | 只看该作者
全局变量与局部变量:全局变量不依赖任何函数,至始至终都存在,存储于静态区

使用特权

评论回复
15
angerbird| | 2014-4-21 22:22 | 只看该作者
局部变量时在函数被调用后才开始分配空间,并最终随函数一起消亡。

使用特权

评论回复
16
angerbird| | 2014-4-21 22:23 | 只看该作者
全局变量显然在整个程序过程都一直存在,而局部变量生于函数调用时,死于函数调用结束。

使用特权

评论回复
17
angerbird| | 2014-4-21 22:23 | 只看该作者
形式参数是函数的局部变量,创建于函数调用时,并被参数赋值。赋值则意味着在被调用函数内的操作,将不会影响到实参的值

使用特权

评论回复
18
firstblood| | 2014-4-22 19:33 | 只看该作者
学习下的啊,局部变量跟全局变量的用法是有很大区别的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

176

主题

1329

帖子

3

粉丝