title: C 语言之变量存储类型与链接属性 layout: post categories: C语言 excerpt: C语言的变量存储类型与链接属性的区别分析
C语言中一个重要的东西就是弄清申明变量的类型、作用域、存储类型、链接属性等,例如是整型还是浮点型,存储于普通内存还是堆栈或者寄存器,作用于全局还是局部,能否被其他文件 引用等。
申明变量或函数时需要标识符,标识符的链接属性一共有三种:external(外部)
, internal(内部)
, none(无)
,external和internal常用,none表示无链接属性,该标识符的多个申明被当成独立不同的实体。
顾名思义,external表示能被其它源文件访问的变量或函数,internal则不能被其它源文件访问,并且缺省情况下代码块(block)外部的变量为external属性,也就是外部变量,代码块内部的变量为internal属性,即局部变量.
如果需要改变链接属性需要使用 extern
和 static
关键字,extern
是转化为external属性,static
是转化为internal属性。
举例说明:
#include<stdio.h>
int a = 1; /* 这里是代码块外部,external 属性,缺省为"extern" */
extern int aa = 11; /* 与上面效果一样 */
static int aaa = 111; /* 这里申明的是 internal 属性,不能被其它源文件访问 */
void example() /* 这里申明的 example() 函数也是external属性,能被其它源文件访问 */
{
int b = 2; /* 这里是代码块内部,internal 属性 */
extern int bb = 22; /* 这里的意思是访问其它源文件的全局变量 */
}
注意上面指出的代码块内部和外部,定义的函数的花括号之外叫做代码块外部,之内叫做代码块内部。 代码块外部缺省为
extern
,并且代码块外部使用extern
表示被其它源文件访问,代码块内部使用extern
表示访问其它文件的外部变量。
存储类型指申明的变量将被存储到什么地方去,并且与其存储周期有关,就是这个变量何时被创建,何时被销毁,保持多久。
存储类型有三种:
静态变量(static
) ---> 存储于普通内存。
自动变量(auto
) ---> 存储于堆栈。
寄存器变量(register
) ---> 存储于寄存器。
任何代码块之外定义的变量,总是处于静态内存中,无需使用 static
关键字,在程序运行之前创建,程序整个执行期间始终存在。
代码块内部申明的变量,并且缺省情况下都是(auto
)类型,所以很少使用,存储于堆栈中,程序执行到申明变量处被创建,离开后被销毁,每次在堆栈中占据的内存位置都可能不同。
用于申明自动变量,即在代码块内部使用,使这类变量存储于寄存器中,寄存器中的变量比内存中的变量访问效率更高。
但是,如果有太多变量申明为 register
,只会选取前几个存储于寄存器中,其它处理为普通自动变量。
通常把使用频率最高的变量申明为寄存器变量,或者指针申明为寄存器变量,以提高效率。例如可以把函数的形参申明为寄存器变量(有可能它节省的时间空间开销抵不上复制这几个值的开销)。
#include<stdio.h>
int a = 1; /* 静态变量(static),这里不能使用 register */
int main()
{
int b = 2; /* 自动变量,省略 auto */
register int c = 3; /* 寄存器变量(register) */
int aaa(register int d) /* 申明函数形参为 register */
static int e = 4; /* 申明静态变量,和变量 b 一个属性 */
}
静态变量在不指定初始值的时候,初始化为 0
;
自动变量是否初始化赋值,并无效率的改变(每次执行都要重新初始化),这也是它的优点:可以用任何“表达式”作为初始值。例如:
int add(int a)
{
int b = a + 1; /* 将表达式 a + 1 的值初始化给 b */
return b;
}
static
申明函数或代码块之外的变量时,只修改链接属性 `external
为 internal
,存储类型和作用域不变。static
申明代码块内部变量时,将自动变量修改为静态变量,但是链接属性和作用域不变。#include<stdio.h>
int a = 1; /* 链接属性为 external,缺省 extern */
static int b = 2; /* 修改连接属性为静态变量,不能被其它源文件访问,依然为全局变量,存储于静态内存中 */
int main()
{
int c = 3; /* 自动变量,存储到堆栈 */
static int d = 4; /* 静态变量,存储到普通内存,依然不能被其它源文件访问 */
}