C语言学习笔记_存储类&作用域&链接属性
C语言学习笔记_存储类&作用域&链接属性
存储类
存储类就是存储类型,也就是描述c语言变量在何种地方存储,
内存中有多种管理方法,栈、对、数据段、bss段、.text段,一个变量的存储类属性就是描述这风格变量存储在何种内存段中;
作用域
一个变量的作用域就是其所在的代码块,也就是上一个大括号所在的区域;
生命周期
生命周期描述的是这个变量什么时候诞生,以及什么时候死亡(即回收此内存地址);
链接属性
程序运行时,变量名、函数名能够和相应的内存对应起来,就是靠符号来做链接的;
.0的目标文件链接生成最终可执行程序的时候,其实就是把符号和相对应的段给链接起来;
c语言中的符号有三种链接属性:外链接、内链接和无链接;
linux下c程序的内存映像
代码段、只读数据段:
对应程序中的代码(函数),代码段在linux中又叫文本段(.text)
只读数据段就是在程序运行期间只能读不能写的数据,const修饰的常量有可能是存在只读数据段的(不一定都是,const常量的实现方法在不同平台是不一样的)
数据段、bss段
数据段保存:1、显式初始化为非0的全局变量;2、显式初始化为非0的static局部变量;
bss段保存:1、显式初始化为0或者未显示初始化的全局变量;2、显式初始化为0或未显式初始化的static局部变量;
堆内存
c语言不会自动向堆内存保存数据,是程序员自己手工操作的,程序根据需求申请、释放;
文件映射区
文件映射是进程打开文件后,将这个文件的内容从硬盘读到进程的文件映射区,以后就直接在内存中操作这个文件,完成后再保存时再将内存中的文件写到硬盘中;
栈
局部变量分配在栈上;函数的调用、传参也是分配在栈上的;
内核映射区
内核映射区就是将操作系统内核程序映射到这个区域
注意,因为操作系统在程序运行前,会加入一段辅助运行代码,帮助程序进行重定位,清理bss段,这就是为什么bss段的变量为0的原因;
存储类相关的关键字
static关键字
static修饰局部变量形成静态局部变量
static修饰全局变量形成静态全局变量
静态局部变量和全局变量的存储类、生命周期是一样的;
静态局部变量和全局变量的区别是:作用域、链接属性;静态局部变量作用域是代码块作用域(和普通局部变量是一样的)、链接属性是无链接的;全局变量作用域是文件作用域(和函数是一样的)、链接属性是外链接;
register关键字
register修饰的变量(一般是全局变量)编译器会尽量将它分配在寄存器中。读写效率会高很多,所以register修饰的变量用在被反复高频率使用的变量中,可以通过此提高程序的效率;
extern关键字
exern主要用于声明全局变量,声明的全局变量可以在其他文件中使用;
由于c语言是按照源文件为单位编译的,所以当需要使用一个其他文件的全局变量时,需要先申明:
extern int GLOBAL_VARIBLE;
使用extern时不要初始化,就可以使用在其他文件的此变量了;
volitle关键字
此关键字字面意思是可变的,此关键字修饰的变量表示此变量可以被编译器以外的东西改变;
编译器之内的改变表示代码更改;
编译器之外的改变表示此改变无法预知,如中断处理程序ISR中更改了;多线程中别的线程更改了;硬件自动更改了(一般此时此变量是寄存器);
restrict关键字
c99中才支持的一个关键字;
告诉编译器只能通过此指针修改变量,用于帮助编译器更好的优化代码
typedef关键字
作用域详解
局部变量的代码块作用域
代码块可以理解为{}括起来的部分
代码块不等于函数
局部变量的作用域是代码块作用域;
函数名和全局变量的文件作用域
文件作用域的意思就是全局的访问权限,也就是说整个.c文件中都可以访问;
函数和全局变量的作用域就是定义的整个.c文件定义式之后的部分;
同名变量的掩蔽规则:同名的局部变量掩蔽全局变量;
链接属性
编译:将函数/变量编译成.o格式的二进制文件;以单个文件进行编译;
链接:将各个独立分开的二进制的函数链接起来形成一个整体的二进制可执行程序;
外链接:即链接范围在整个程序,可以跨文件链接;
内链接:即链接范围在当前文件,不能跨文件链接;
无链接:不参与链接;
链接属性可用于解决全局变量/函数的重名问题:
对不会再其他c文件中引用的函数/全局变量,使用static修饰使其成为内链接属性,这样就可以防止其与其他文件中的全局变量重名;
存储类决定生命周期,作用域决定链接属性;
宏和inline函数的链接属性为无连接;