您的位置:首页 > 编程语言 > C语言/C++

C语言编程之存储模型、链接

2016-06-20 09:57 239 查看
C语言编程之存储模型、链接

变量是程序中数据的存储空间的抽象。变量的存储方式可分为静态变量和动态变量两种。

静态存储通常是在程序编译时就分配一定的存储空间并保持不变,直到整个程序运行结束才得以释放。例如函数中全局变量的存储就采用静态存储。
动态存储变量是程序执行过程中使用它时才分配空间存储单元,使用完后立即释放。例如函数的形参。


由以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。由于不同变量存储方式的不同而产生的特性称为变量的生存期,生存期表示了变量存在的时间。

生存期和作用域是从时间和空间这两个不同的视角描述变量的特征。两者既有联系,又有区别。一个变量究竟处于哪一种存储方式,并不能仅从作用域来判断,还应有明确的存储说明。

变量的存储模型由作用域、链接点和存储期三大属性描述。其中,存储期描述的是变量在内存中的生存时间。存储模型也常称为存储类,共有以下5种存储模型:

1、自动 auto
auto为存储类说明符,可以说明一个变量为自动变量。该类具有动态存储期、代码块的作用域和空链接。如果变量没有初始化,他的值是不确定的。
代码块或函数头部定义的变量,可使用存储类修饰符auto来明确标识其属于自动变量,若没有使用auto修饰,依然属于自动存储类型。
例如:`{
int i,j;
char c;
}`
等价于`{
auto int i,j;
auto char c;
}`
自动变量具有以下特点:
①、自动变量的作用域限于定义该变量的模块内。在函数中定义的自动变量,只在该函数内部有效。在复合语句中定义的自动变量,只在该复合语句中有效。
②、自动变量属于动态存储方式,只有在定义该变量的函数被调用才给他分配存储单元,开始他的生命周期。函数调用结束,释放存储单元,结束其生命周期。因此在函数调用结束之后,自动变量的值不能被保留。再复合语句中定义中的自动变量,在复合语句退出后变不能再被使用,否则会引起错误。
③、由于自动变量的作用域和生存期都局限于定义他的模块内,因此,在不同模块中允许使用同名的变量而不会引起混淆。函数内定义的自动变量可以与该函数内部复合语句中的自动变量同名,但应尽量避免这种方式。

2、寄存器 register
在一个代码块内使用修饰符register声明的变量属于寄存器存储器存储类。register修饰符暗示编译程序相应的变量将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,从而加快存取速度。该类与自动变量相似,具有自动存储期、代码块作用域和空,空链接。如果没有初始化,其值也将是不确定的。
使用register修饰符有几点限制
①、register变量必须是CPU寄存器所能接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度。
②、声明register只是一个请求,而非命令,因此变量仍有可能是普通的自动变量,并没有被放在寄存器中。
③、由于变量有可能存储在寄存器中,而非在内存中,因此不能用取地址运算符&获取register变量的地址。
④、只有局部变量和形参可以作为register变量,全局变量不行。
⑤、实际上有些系统并不把register变量存放在寄存器中,而优化的编译系统则可以自动识别频繁被使用的变量而把他们放在寄存器中。
3、静态、空链接 static
静态变量的类型说明符:static。在一个代码块内使用存储类修饰符static声明的局部变量属于静态空链接存储类。该类具有静态存储期、代码块作用域和空链接。
静态变量的存储空间是在编译完成后就分配了的,并且在程序运行的全部过程中都不会撤销。需要注意区别的是,属于静态存储方式的变量不一定是静态变量。例如,外部存储变量虽属于静态存储方式,但不一定是静态变量。
静态局部变量属于静态存储方式,它具有以下特点:
①、静态局部变量在函数内定义,他的生存期为整个程序执行期间,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但已不能使用它。
②、可以对构造静态局部变量赋初值,例如数组,若未赋初值,则系统自动初始化为0
③、基本数据类型的静态局部变量若在声明时未赋初值,则系统自动赋0.而对自动变量不赋初值,其值是不确定的。因此,静态局部变量的生存期为整个程序运行期。虽然离开了定义它的函数后不能使用,**但若再次调用定义他的函数时,它又可以继续使用,并且保留上次被调用后的值。**
4、静态、外部链接 static extern
未使用static修饰的全局变量属于静态、外部链接存储类。具有静态存储时期、文件作用域和外部链接。仅在编译时初始化一次。如未明确初始化,它的字节也被设定为0.在使用外部变量的函数中使用extern关键字来再次声明。如果该变量是在其他文件中定义的,则必须使用extern。
5、静态、内部链接
全局变量再次被冠以static就构成了静态的全局变量,属于静态、内部链接存储类。与静态外部存储类不同的是,具有内部链接,使得仅能被与它在同一个文件中的函数使用,这样的变量也仅在编译时初始化一次。若未明确指定初值,其值被设为0.
静态全局变量与非静态全局变量的区别:
非静态全局变量的作用域是整个源程序,但当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的;而静态全局变量则限制了其作用域,即只在定义该变量的源文件内使用,在同一源程序的其他源文件中不能使用。
由于静态全局变量的作用域局限于一个源文件内,只能被该源文件内的函数使用,因此可以避免在其他源文件中引起错误。


链接属性

组成一个程序的各个源文件分别被编译后,所有的目标文件以及那些从一个或多个函数库中引用的函数链接在一起,形成可执行程序。如果相同的标识符出现在几个不同的源文件中时,他们的标识符的链接属性决定了他们是同一个变量还是不同的变量。
1、空链接
作用域为代码块作用域或者函数原型作用域的变量,为空链接。当具有空链接的相同的变量名出现在几个不同的源文件中时,他们是由其定义所在的代码块或函数原型所私有的,被当作独立不同的实体。
2、内部链接
使用static声明的全局变量,属于文件作用域,在文件的任何地方都可以使用,这就是内部链接。属于内部链接的变量在同一个源文件内的所有声明中指同一个变量,但位于不同源文件的多个声明则属于不同的变量。需要注意的是,static只对全局变量的声明,有该变链接属性的效果。若声明的是局部变量,会使这个变量成为静态变量,延长了变量的使用周期,使得变量在程序的整个运行期间都存在,直至程序运行结束。
3、外部链接
全局变量,可以在文件的任意地方使用,默认是外部链接。属于外部链接属性的变量,无论声明多少次、位于几个源文件中都标识同一个变量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 全局变量