C中储存类别与链接的大致总结
C中储存类别与链接的大致总结
资料来源于 C Primer Plus 这本书,还有在别的地方学到的相关知识的理解
并不全面但应该有点用处
1.概述
对于想要快速回忆细节的需求准备的总表
C 中有5种储存类别:
储存类别 | 存储期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内,缺省或者auto 关键字 |
静态无链接 | 静态 | 块 | 无 | 块内,static 关键字 |
寄存器 | 自动 | 块 | 无 | 块内,register 关键字 |
静态外部链接 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部 | 所有函数外,static 关键字 |
2.块内作用域中 的类别
所谓的块大体指的是一个{}
内的代码,C99 开始if
或者while
这类语句的不加大括号的版本中的那行代码也算是一个块
if (true)
puts("hello"); // 这一行也算一个块
2.1.缺省/自动(auto)
默认的储存类型又称自动类型,它们可以在其声明时所在的块内调用,除了函数内的表达式没有别人能使用它们了
这种类型也可能会被叫做”局部变量”
2.2.静态无链接
加上了static
关键字的储存类型,表达式依然需要在块内才能访问它
但用于它是静态类型,所以在每次调用完函数后变量对象并不会重新释放
// 一段超棒的演示代码
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
打印的输出:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
可以去看看… stackoverflow上的 What does “static” mean in C?
3.文件作用域 中的类别
文件作用域是指不被任何函数包裹的区域,也就是常说的”全局变量”所定义的区域
#include <stdbool.h>
int variable1; // 这里就是文件作用域
int main()
{
// 这就是块作用域
}
到了这里static
关键字就从确定静态类型,转换为确定链接类型,所有文件作用域的变量都是静态变量
此处的链接
大体上指的是其他的 .c 文件能否访问的到这个变量
更确切的说是,每个c预处理器的翻译单元之间的变量能否互相访问
详情可以去搜索引擎上翻一翻,我几乎是全看书了解的,也顺便放一个维基百科(EN)的链接 Translation unit (programming)
另外,每个翻译单元之间链接了的变量也不能直接访问,仍然需要extern
关键字声明该变量已经在别处定义过了
extern
并没有定义变量,而是像函数原型那样,告诉下面有需要表达式变量存在但需要去别处寻找
3.1.静态外部链接
能在所有文件中访问的变量
// file1.c
#include <stdbool.h>
int a233 = 233;
// file2.c
#include <stdbool.h>
extern int a233; // 声明变量存在
void fun()
{
// 正常访问 a233
}
3.2.静态内部链接
只能由定义时所在文件的翻译单元访问的变量
// file1.c
#include <stdbool.h>
static int a233 = 233;
// file2.c
#include <stdbool.h>
extern int a233; // 编译器应该会报错
void fun()
{
// 炸毛
}
4.寄存器类型
没什么用
原先是用来说明变量需要高强度使用的,不过现在嘛…编译器比你更懂你的程序
即使用了这个关键字也照样只是请求将变量放入cpu寄存器而非绝对的命令,编译器甚至可能都会忽略他们转而继续自己调度内存
所以请不要管它
5.EOF
没咯
记得善用搜索引擎,这里只是简单的记录和总结一下,省略了不少书中的前置知识和细节