【C语言学习】C语言中的函数
代码中,函数是为了更好的实现模块化的程序设计。那么函数的本质是什么?函数中定义的变量(全局变量、局部变量、静态变量等)又是怎样存储的?为什么全局变量与局部变量的作用域和生命期不相同?只有更加深入的了解函数,才能解答这些问题!
★函数的本质
函数的本质是一段可执行的机器指令代码,函数名的本质是一个标号,表示函数代码的入口。该标号的值等于内存中存储函数代码的内存空间的首地址。
★变量
●全局变量
全局变量也就是外部变量,定义在函数的外部。因此它不属于任何一个函数,只属于所在的源文件。
▲初始化
对于全局变量来说,如果没有被初始化,其值由编译器自动设置为0。因此,使用一个全局变量不用考虑它的初始化问题。
运行结果:
▲作用域和生命周期
其作用域从定义该变量的这一行开始到定义该变量的源文件结束,在此期间,所有的函数都可以引用该变量。这里有一点要注意:全局变量作用域的范围并不是从程序的开始一直到程序的结尾,而是从定义这个变量的开始处到程序的结尾。
有这样一种情况:在一个源文件中,定义全局变量之前已经定义了一个函数A,那么A就不能引用这个全局变量。如果非要引用这个变量,那么就先在A之前声明这个全局变量。
●局部变量
局部变量也成为内部变量,它定义在函数或者复合语句的内部。
▲初始化
如果局部变量未被初始化,那么直接引用会很危险。因为局部变量存储于内存的堆栈中。定义了局部变量之后,编译器不会将其初始化为0,而是此内存空间原来的值。那么这个值是一个随机值,最后就可想而知了。因此,局部变量一定要记得初始化!
运行结果:
▲作用域和生命周期
因为它定义在函数内部或者复合语句的内部。因此,其作用域仅限于函数或者符合语句内。
★变量存储
源文件中,不同的变量存储在不同的区域内。一个程序在运行期间会占用内存,并且内存的使用情况也不同。一般会分为:数据段、代码段、堆栈段、BSS段
●BBS段(Block Started by Symbol)
通常用来存储未初始化全局变量和静态变量的一块区域。BSS段属于静态内存分配。在程序执行之前,BSS段会自动清零。这也就是前面全局变量不用初始化的原因。
●代码段
用来存放程序的执行代码。这段内存在程序运行之前就已经确定。
●数据段
通常用来存放已经初始化的全局变量和静态变量。属于静态内存分配。
●堆
用来存放程序动态分配的内存空间,大小不固定。可扩张、可缩减。当调用malloc函数时,就是从堆上分配内存,内存空间扩大;调用free函数时,堆上内存空间就会缩减。
●栈
用来存放函数内部定义的局部变量(注意:不包括static声明的变量,一般存储在数据段中)。在函数被调用时,其参数也会被压入发起调用的堆栈中,并且待到调用结束后,函数的返回值也会被放会栈中,由于栈的先进后出的特点,所以栈特别方便用来保存/恢复调用现场,从这个意义来讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
★函数有关的优化
●函数调用优化
函数的作用是使代码模块行增强,有利于代码的阅读和修改,可以有效的缩减代码的体积。但是函数调用是很费时的,一个函数调用一般有4步:
1、需将参数压入堆栈
2、需要保存寄存器的值
3、需要保存返回地址
4、会造成跳转
这四步中以上3步都需要访问内存。访问内存是很消耗时间的,如果程序中调用函数过多,其运行的速度肯定会很慢。因此在程序执行过程中,应该尽量减少不必要的函数调用,这样才能提高程序的执行速度。
●变量存储优化
由于局部变量存储在栈上,全局变量存储在数据段上。由于两者的存储位置不同导致生命周期的不同。
对于程序中调用很高的局部变量,编译器会自动将其存储在寄存器中,但是全局变量不会被存储在寄存器中。因为全局变量在整个程序中一直存在,如果全局变量存储在寄存器中,那么寄存器就无法存储临时变量或者中间值。计算机中,寄存器资源本来就稀少,程序的运行效率也没有效率。因此,全局变量一定要存储在数据段上,也就是内存中。尽量减少内存的访问也是提高程序执行速度的方法!(寄存器位于CPU中,它的特点是:容量小,速度快。如果一些变量被频繁的使用,就将此变量存储于寄存器中。这样就会减少对内存的频繁操作,从而节约了时间)
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。