存储的基本概念
- 对象
存储值的物理内存
面向对象编程的对象指的是类对象,c不是面向对象编程的语言。
- 标识符
指定特定对象的内容
描述对象与标识符的方法:
1. 作用域->程序中可访问标识符的区域
以块(花括号{}为一个块)来划分
声明在内层块中的变量,作用域只限定于声明变量的块。
名称 | 含义 |
---|---|
块作用域 | 从块开始到块结束 |
函数作用域 | 声明在函数中的变量能作用于这个函数 |
函数原型作用域 | int Func(int,int) 从形参声明到函数原型结束,所以声明时函数参数无关紧要。 |
2.链接->指定标识符的私有(可见)范围
- 内部链接
内部链接指在此变量的作用域下只有所在的部分可以访问。
例如文件作用域,那么内部链接只有此翻译单元内的函数可以访问它
函数作用域会如何?!事实上我们说链接作用域只有文件作用域
- 外部链接
所有在此作用域的部分都可以访问。
3.存储期->对象的生产周期
名称 | 含义 |
---|---|
静态存储期 | 程序执行期间一直存在 |
线程存储期 | 线程执行期间一直存在 |
自动存储期 | 从块开始到块结束(变长数组从声明开始) |
变量的存储类别:
那么,描述对象和标识符的三个方法组合起来,构成了下面5种存储类别。
存储类别 | 存储期 | 作用域 | 链接 | 表达方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内 |
寄存器 | 自动 | 块 | 无 | 块内,使用关键字register |
静态外部 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部 | 静态 | 文件 | 内部 | 所有函数外,使用关键字static |
静态无链接 | 静态 | 块 | 无 | 块内,关键字static |
那么这些存储类别的变量,根据存储期、作用域与链接三个方法可以得出这些存储类别的特点以及使用方法。
- 自动变量
块开始到块结束这段时间变量存在,在这个块内可以被访问(看到)。 - 寄存器变量
和自动变量的定义完全相同,但寄存器变量访问更快。但不能寻址 - 块作用域的静态变量
通常把块作用域,无链接的静态变量称为静态变量。
在块作用域中可见,没有链接,程序结束前都存在。
void Func(void){
int fade=1;
static int state=2;
printf("fade=%d and state=%d",fade++,state++)
以上代码块中,第3行的声明其实并不属于这个函数,静态变量和外部变量在载入内存时已执行完毕,把这条语句放到这里意思是只有这个函数可以看到这个变量。
- 外部链接的静态变量
该类别有时候被称为外部存储类别,属于该类别的变量被称为外部变量。
为了指明函数使用了其他文件的外部变量,可以用extern
声明
当使用的外部变量在另一个文件中定义时,必须用extern
声明 - 内部链接的静态变量
只能被定义处的文件访问,而不能被其他文件访问。作用域范围为文件作用域。
静态链接和内部链接的静态变量区别就是作用域不同,前者是针对于块作用域而后者为文件作用域!
函数的存储类别
函数存储类别也有外部函数(默认),静态函数以及内联函数。
int Func(double);//默认为外部函数
extern Func1(double);//显式定义为外部函数
static int Func2(int,int);//定义为静态函数
外部函数可以被其他文件访问,而静态函数之内用于定义了它的文件访问。
来写一个随机数种子结束这一块内容!
#include<stdio.h>
#include<time.h>
static unsigned long int ne;
unsigned rand0() {
ne = ne * 1103515245 + 12345;
return (unsigned int)(ne / 65536) % 32786;
}
void seed1(int seed) {
ne = seed;
}
int main() {
seed1(time(0));
for(int i=0;i<4;i++)
printf("%d\n",rand0());
}
time()包含在头文件time.h中,time()接受一个time_s类型的参数,可以用空指针来初始化。