C语言中存储类别也就是storage class,它的定义是在一个C程序里面变量variables和函数functions的可见作用域(visible scope)和生命周期(life-time),我们有5种存储类别:
存储类别 | 存储期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内 |
寄存器 | 自动 | 块 | 无 | 块内,使用关键字register |
静态外部链接 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部 | 所有函数外,使用关键字static |
静态无链接 | 静态 | 块 | 无 | 块内,使用关键字static |
存储类别是提供给我们在内存中存放数据的,它的基本单位是块,我们把这样一块内存成为对象(object),object是存放数据的memory location, object相当于一间房,我们在房间里可以放一个物品,也可以放多个物品,前提是不要满了,因为硬件上给的内存是有限的,当然我们也可以不放。object作为memory location是不变的,但是存储的数据是可以变的,比如对于自动变量,它没用前不占用,用完后变量消失,也不占用。然后咱们再来说说变量variables,程序需要一种方法来访问咱们的object,比入
char *pt = "something";
int str = 5;
在这个例子里,pt便是指向对象的,对象是"something",这是一个内存地址,我们使用了指针来指向object,我们也可以使用(pt+2)来指向字符'm'的地址,他是一个可以改变的左值,str是标识符identifier,那么他是用来指向特定对象的内容,在这里对象就是&str,内容是5。
那么标识符可以访问对象,那么我们使用作用域scope和链接linkage来描述它
##什么叫做作用域
作用域就是一个变量的作用范围,比如
int global = 4; //全局变量,整个程序都可见
int keng(int pt) //pt作用域开始
{
int i;
for(i=0;i<10;i++)
{
int p=0; //p作用域开始
global+=pt+p;
} //p作用域结束
return global;
} //pt作用域结束
显然p是块作用域,它只在定义p后的for循环块里是有效的,而pt是函数作用域,他在函数keng里面是有效的,出了函数就不可见了。而变量global是文件作用域,它在整个文件中是可见的,包括下面的所有函数,我们也通常称之为全局变量(global variable)
linkage在维基百科中是这样定义的
linkage describes how names can or can not refer to the same entity throughout the whole program or one single translation unit.
也就是链接描述了变量名是否能通过整个程序或者翻译单元来指向相同的对象。通俗点就是我定义了一个变量名,然后我其他地方也有相同的变量名,两个变量名是否指向同一个位置,我的地址是否是一样的。C变量有三种链接属性:外部链接,内部链接以及无链接。具有块作用域、函数(原型)作用域的变量都是无链接属性,属于这些定义他们的块、函数所私有,出了这个界,哪怕是相同名字的变量,那意义也不同了。外部链接变量可以在多文件程序中使用,而内部链接只能在一个翻译单元(一个源代码文件和它所包含的.h头文件)使用。区分外部链接和内部链接的方式是内部链接使用关键字static,默认是外部链接。
存储期是描述通过标识符访问的对象的生命期,而生命期是指为变量或者函数从分配内存到释放的内存的一个持续时间,C一共有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。
void function[int number]
{
static int m = 0; //块作用域,但是静态存储期,无链接
number+= m; //number是块作用域,但是自动存储期,无链接
m++;
}
特别注意的是块存储里的用static关键字的变量是在程序进入内存就已执行完毕,不是到了函数这里才执行,遇到它函数会选择跳过。举个例子:
#include <stdio.h>
void est(void);
int main()
{
int number;
for (number = 0; number < 4; number++)
{
est();
}
}
void est(void)
{
int n = 0;
static int m = 0;
printf("n=%d,m=%d\n",n++,m++);
}
执行代码后结果为:
因为n是自动存储变量,每次循环都会执行n=0的语句,所以n始终为0,而m是静态变量,m只在程序载入内存时执行,在函数里是不会再次执行的。
对于内部链接我们一般用static,对于外部链接,你可以不用关键字,用关键字其实目的是提醒读者这是一个外部链接变量,通常当我们读到多个源文件时,外部变量只声明一次,在其他地方,一般会用关键字extern,提醒你这个变量是整个程序共用的。对于寄存器变量,我们使用关键字register,如果寄存器愿意的话(因为寄存器存储空间有限,你的大小要是很大寄存器会有可能拒绝)。这样做的好处是你的变量处理会很快,缺点是无法获得这个变量的地址,如果你用函数想返回这个值到主函数是不可能的,因为指针没用了。
总的来说,存储类别搞清楚作用域、存储期、链接以及它们的四个声明方式,就能很好的区分了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。