变量的存储模型(存储类)可以用变量的作用域以及它的链接和存储时期来描述。
作用域,描述了程序中可以访问一个标示符的一个或者多个区域
- 代码块作用域:在代码块中定义的变量,在该定义的代码块中该变量可见
- 函数原型作用域:对函数进行声明的时候,其实在这个时候编译器并不在乎参数变量名,而只是关心参数变量的类型
- 文件作用域:在所有函数之外定义的变量,包括main函数
链接,C语言变量具有外部链接、内部链接和空连接三种类型
- 具有代码块作用域和函数原型作用域的变量有空链接,它们由其定义所在的代码块或者函数原型所私有
- 具有文件作用域的变量可能有内部链接或者外部链接,具有外部链接的变量可以在多个文件的任何地方使用,具有内部链接变量可以在一个文件中声明之后的任何地方使用
存储时期,C语言变量具有静态存储时期和自动存储时期两种存储时期,如果一个变量具有静态存储时期,它在程序执行期间一直存在。具有文件作用域的变量都具有静态存储时期,如果在具有文件作用域的变量前加上static表明链接类型为内部链接,不表明存储时期。
C使用作用域、链接和存储时期来定义了5种存储类:自动、寄存器、具有代码块作用域的静态、具有外部链接的静态、以及具有内部链接的静态
自动变量:使用auto存储类型说明符为关键字定义变量,具有自动存储时期、代码块作用域和空链接。不需要显式地使用auto关键字来定义自动变量,编译器不会自动进行初始化
int main(void)
{
auto int x; //不用显式地使用auto关键字,如果在外部也同样定义了x变量,这里将会有内层定义覆盖外部定义
}int main(void)
{
int x = 30;
while(x++ < 33)
{
int x = 100; //重新定义x,覆盖外部定义的x变量
printf("x in while loop: %d\n", x);
}
}上面while例子中,每次循环结束后,在while中定义的x都会消失,然后用最初定义的x来作为while循环的条件判断寄存器变量:使用register存储类型说明符为关键字定义变量,具有自动存储时期、代码块作用域和空链接,把变量存放在CPU的寄存器中,将会有更快的访问和操作速度。因为寄存器变量是存放在一个寄存器而非内存中,所有无法获得寄存器变量的地址。声明寄存器变量仅仅是一个请求,而不是一个命令,编译器将会权衡是否作为寄存器变量,如果申请不成功,就会作为自动变量。
int main(void)
{
register int x;
}具有代码块作用域的静态变量:在代码块中定义变量加上static存储类型说明符,在代码块作用域结束后,该变量不消失,具有静态存储时期、代码块作用域和空链接。具有代码块作用域的静态变量只在编译的时候初始化一次,如果不显式地对静态变量进行初始化,编译器将会把它们初始化为0
while(x < 3)
{
static int x = 1; //只在编译的时候初始化为1,在进行后面的循环的时候,将跳过这一步
printf("%d", x++);
}
void static_fun(static int x); //不能用static变量来做函数参数
具有外部链接的静态变量:使用extern存储类型说明符为关键字定义变量,具有静态存储时期、文件作用域和外部链接,可以在多个文件中使用该变量。这里看一下变量定义和变量声明的区别,关键字extern的存在标志一个引用声明,而非定义声明
int x = 1; //变量的定义
void main(void)
{
extern int x; //这里只是声明变量,不是对变量的定义,说明可以使用外部定义的变量
}具有内部链接的静态变量:使用static存储类型说明符为关键字定义变量,具有静态存储时期、文件作用域和内部链接,只可以在本文件中声明之后的任何地方使用该变量。
补充:函数存储类型
函数同样也具有存储类型,函数默认情况下是外部的
int fun1();
static int fun2();
extern fun3();函数fun1()和fun3()可以被程序中的其他文件中的函数调用,而fun2()函数不行,只能在定义该函数的文件里被调用。
5710

被折叠的 条评论
为什么被折叠?



