***存储类:
就是存储类型,描述,C语言变量的存储地址。
内存的管理方式:栈 堆 数据段 bss段 .text段。
一个变量的存储类型就是描述这个变量存储在何种内存段之中。
***作用域:
描述变量起作用的范围。
函数名和全局变量是文件作用域,在整个.c文件夹之内都可以访问这些东西。
同名变量的掩盖规则:局部变量会掩盖全局变量(就近原则)
***生命周期:
描述变量诞生(运行时分配内存空间)和死亡(运行完回收内存空间)的时间在
局部变量储存在栈上,生命周期是临时的,在代码执行的过程中按照需求去创造,使用,消亡。局部变量在每一次被调用时都会重新被创建,使用,消亡。
堆内存:堆内存空间客观存在,由操作系统维护,我们程序只是去申请,使用完再释放。其生命周期就是malloc申请~free消亡。
数据段和bss段:全局变量生命周期时永久的,在程序被执行时诞生,程序终止时消亡。他占有的内存是不能被释放的。所以不能申请太多的全局变量。
代码段和只读数据段:其实就是函数,生命周期永久。
***链接属性:
编译阶段就是将源代码变成.o目标文件,目标文件包括很多的符号,代码段,数据段,bss段。符号是编程中的变量名,函数名。运行时变量名,函数名能够和对应的内存对应起来,就靠符号来做链接的。
. o的目标文件链接生成最红可执行文件时,其实就是把无符号和对应的段给链接起来。C语言的符号有三种链接属性:外链接属性,内链接属性,无链接属性。
C语言的组织架构:多个c文件+多个h文件。
程序的生成过程就是编译+链接。编译时为了将函数/变量变成.o二进制机器码,链接是为了将独立分开的二进制函数链接起来形成一个整体的二进制可执行程序。
编译以文件为单位,链接以工程为单位。
外链接就是可以在整个程序内进行链接(可以跨文件),例如函数和全局变量。
内部链接在当前c文件内进行链接,不能跨文件。例如static修饰的函数,全局变量
无链接就是符号本身不参与链接,例如所有的局部变量
static第二种用法:修饰局部变量和函数
普通的函数/全局变量,默认链接属性是外部的。
static(静态的)函数/全局变量,链接属性是内部链接。
***linux下C语言程序的映像:
代码段,只读数据段:对应着程序中的代码段,代码段在linux中叫文本段(.text)
数据段,bss段:
1.数据段存放显示初始化为非0的全局变量,显示初始化为非0的static的局部变量。
2.bss段存放显示初始化为0,或者未显示初始化的全局变量,显示初始化为0或者未显示初始化的static局部变量。
3.文件映射区:进程打开文件之后,将这个文件的内容从硬盘读取到进程的文件映射区,以后就直接在内存中操作这个文件,读取完了后在保存时再将内存中的文件写到硬盘之中去。
4.内核映射区:将操作系统的内核程序映射到这个区域。对于每一个linux进程来说,整个系统只有自己和内核而已。(运用了虚拟地址技术)
***存储类相关关键字
1.auto:仅仅只有一种作用:修饰局部变量,表示这个局部变量是自动局部变量,分配在栈上面。 则如果不初始化则值是随机的,生命周期是临时的。auto局部变量就是默认定义的普通局部变量。
**2.static用法:1).用来修饰局部变量,形成静态局部变量。
注:静态局部变量和非静态局部变量二者的区别是存储类不同。非*分配在栈上面,静态分配在bss段。
2).修饰全局变量,形成静态全局变量。
注:静态全局变量和非静态全局变量的区别:链接属性不同。
静态局部变量和全局变量存储类,生命周期相同,作用域和链接属性不同。
静态局部变量作用域是代码块,链接属性无连接;
全局变量的作用域是文件作用域,和函数是一样的,链接属性是外链接。
3.register:一个作用:一般全局变量用其修饰。由其修饰的全局变量编译器会尽量将他分配在寄存器中。(一般分配在内存之中)分配在寄存器中使得读写速度加快。register多用来修饰被反复高频率使用的变量,可以通过改善这个变量的访问效率极大提高程序的运行速度。
**4.extern:声明全局变量,目的主要是在a.c中定义变量,在b.c使用变量。 在a.c使用***前先用extern 声明***,并且它的原型和声明相同。链接时连接器会在别的.O文件之中找到这个同名变量。(前提是两个.c文件必须在同一个文件夹内)
**5.volatile:修饰一个可以被编译器之外的东西改变的变量。(编译器之内意思是变量值的改变是代码的作用,编译器之外意思是变量值的改变不是当前代码造成的,编译器在编译当前代码时无法预知。例如中断更改引用的变量,多线程更改公用的变量,以及寄存器直接更改变量值等)编译器在遇到volatile修饰的变量时,不会对其进行优化。
6.restrict:和编译器的优化处理有关的,只用来修饰指针,不能修饰普通变量。
***总结:
1.普通的局部变量自动分配在栈上,作用域是代码块区域,生命周期是临时的,链接属性为无链接。定义时如果未初始化则值是随机分配的,变量的地址由运行时栈上分配得到的,多次执行时地址不一定相同,函数不能返回该变量的地址(指针)作为返回值。
2.静态局部变量分配在数据段/bss段(显示初始化为非0则在数据段,为0或者未显示初始化则在bss段,)作用域是代码块作用区域,生命周期永久,链接属性为无链接。定义时如果未初始化则值为0,变量的地址由运行时环境在加载程序时环境在加载地址时确定,整个程序运行时唯一不变;静态局部变量其实就是作用域为代码块区域的局部变量。惊天局部变量可以用全局变量实现。(程序避免太多的全局变量,破坏程序结构性)
3.静态全局变量/静态函数和普通全局变量/普通函数的唯一差别是:static使用全局变量/函数的链接属性由外部链接转为内部变量。
注:定义的同时初试化则一定会被认为是定义;定义时未初始化则会被认为是定义或者声明;
使用extern被认为是声明,(实际上也有定义,实际上就是声明这个变量为外部链接)