c语言中变量、函数的存储类、作用域、生命周期、连接属性间的关系

1、普通(自动)局部变量分配在栈上,作用域为代码块作用域,生命周期是临时,连接属性为无连接。定义时如果未显式初始化则其值随机,变量地址由运行时在栈上分配得到,多次执行时地址不一定相同,函数不能返回该类变量的地址(指针)作为返回值,因为没有意义。
2、静态局部变量分配在数据段/bss段(显式初始化为非0则在数据段,显式初始化为0或未显示初始化则在bss段),作用域为代码块作用域(人为规定的),生命周期为永久(天然的),链接属性为无连接(天然的)。定义时如果未显式初始化则其值为0(天然的),变量地址由运行时环境在加载程序时确定,整个程序运行过程中唯一不变;静态局部变量其实就是作用域为代码块作用域(同时链接属性为无连接)的全局变量。静态局部变量可以改为用全局变量实现(程序中尽量避免用全局变量,因为会破坏结构性)。
3、静态全局变量/静态函数和普通全局变量/普通函数的唯一差别是:static使全局变量/函数的链接属性由外部链接(整个程序所有文件范围)转为内部链接(当前c文件内)。这是为了解决全局变量/函数的重名问题(C语言没有命名空间namespace的概念,因此在程序中文件变多之后全局变量/函数的重名问题非常严重,将不必要被其他文件引用的全局变量/函数声明为static可以很大程度上改善重名问题,但是仍未彻底解决)。
4、写程序尽量避免使用全局变量,尤其是非static类型的全局变量。能确定不会被其他文件引用的全局变量一定要static修饰。因为在各个不同的.c源文件中,不加static的全局变量/函数很容易出现重名现象。
5、注意区分全局变量的定义和声明。一般规律如下:如果定义的同时有初始化则一定会被认为是定义;如果只是定义而没有初始化则有可能被编译器认为是定义,也可能被认为是声明,要具体分析;如果使用extern则肯定会被认为是声明(实际上使用extern也可以有定义,实际上加extern就是明确声明这个变量为外部链接属性)。
6、全局变量应该定义在c文件中并且在头文件中声明,而不要定义在头文件中(因为如果定义在头文件中,则该头文件被多个c文件包含时该全局变量会重复定义)。
7、在b.c中引用a.c中定义的全局变量/函数有2种方法:一是在a.h中声明该函数/全局变量,然后在b.c中#include <a.h>;二是在b.c中使用extern显式声明要引用的函数/全局变量。其中第一种方法比较正式。
8、存储类决定生命周期,作用域决定链接属性
注:(1)存储类型决定生命周期:存在栈上(普通局部变量),生命周期就是临时的;存储在数据段上(全局变量和static局部            变量),生命周期就是永久的;存储在堆上,生命周期就是mallocal到free之间;存储在代码段(函数、const常量、字符串          常量)上,生命周期就是永久。
       (2).作用域决定连接属性:作用域为代码块作用域(局部变量),链接属性就是无连接;作用域为文件作用域(普通全局            变量/函数),连接属性就是外链接;作用域为本文件范围内(static全局变量/函数),连接属性就是内链接。
9、宏和inline函数的链接属性为无连接。(编译时会被原地展开)

猜你喜欢

转载自blog.csdn.net/weixin_39330853/article/details/81978055