1.存储类别
被存储的每个值都占用一更的物理内存,C语言把这样的一块内存叫做对象。一个对象可以存储一个或多个值。一个对象可能未存实际的值,但是在储存适当的值时一定具有相应的大小。
可以用存储期来描述对象,用标识符访问对象。用作用于和链接藐视标识符。
1.1作用域
作用域描述程序中可访问标识符的区域。块作用域、函数作用域、函数原型作用域或文件作用域。
块作用域:如函数体,定义在块中的变量具有块作用域,
double blocky(double cleo)
{
double patrick = 0;
...
return patrick;
}
其中花括号里的变量都具有块作用域,但花括号前的形参定义也具有块作用域,属于该函数体。
函数作用域仅适用于goto语句。
函数原型作用域用于函数原型中的形参名。
int mighty(int mouse, double large);
从形参定义处到原型声明结束。编译器在处理函数原型中的形参时只关心它的类型,形参名无关紧要。只有在变长数组中形参名才有用。
void use_a_VLA(int n, int m, ar[n][m]);
文件作用域:定义在函数外面的变量具有。从定义处到该定义所在文件的末尾均可见。
#include <stdio.h>
int units = 0;/*该变量具有文件作用域*/
void critic(void);
int main(void)
{
...
}
void critic(void)
{
...
}
main()和critic()都可以使用变量units。也成全局变量。
PS:C预处理是用包含的头文件替换#include指令。所以编译器源代码文件和所有的头文件都可以看成是一个包含信息的单独文件,被称为翻译单元。而文件作用域作用于整个翻译单元。
1.2链接
“内部链接的文件作用域”简称“文件作用域”,“外部链接的文件作用域”简称“全局作用域”。存储类别说明符,static。
int giant = 5; //文件作用域,外部链接
static int dodgers = 3; //全局作用域,内部链接
int main(void)
{
...
}
1.3存储期
静态存储期,程序执行期间一直存在。
线程存储期,从声明到线程结束一直存在。
块作用域的变量具有自动存储期,退出块时释放内存。变长数组从声明处开始而不是块开始处。当块作用域变量声明时加上static关键字,可以拥有静态存储期。
void more(int number)
{
static int ct = 0;
...
return 0;
}
只要在执行该函数时,程序才能通过ct访问它所指对象,但是该函数可以提供该存储区的地址以间接访问该对象,如指针形参或返回值。
另五中存储类别,
存储类别 | 存储期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内 |
寄存器 | 自动 | 块 | 无 | 块内,使用关键字register |
静态外部链接 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部 | 所有函数外,使用关键字static |
静态无链接 | 静态 | 文件 | 无 | 块内,使用关键字static |
1.4多文件
多文件共享一个外部变量时,除一个定义式声明外,其他声明都要使用extern关键字,而且只有定义式声明才可以初始化变量。
PS:如果外部变量定义在一个文件中,那么其他文件在使用变量之前必须声明它(extern关键字)
1.5存储类别和函数
外部函数或静态函数,C99多了内联函数。
通常用extern声明定义在其他文件中的函数,除非使用关键字static,否则默认extern。