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

没咯
记得善用搜索引擎,这里只是简单的记录和总结一下,省略了不少书中的前置知识和细节