参考:https://en.cppreference.com/w/c/language/storage_duration
storage-class specifier 简介
1、 At most one specifier may be used, except that _Thread_local may be combined with static or extern to adjust linkage (since C11).
除了 _Thread_local 可以和 extern static 搭配使用外,存储类型 指示符 最多只能使用 1 个。
2、 The storage-class specifiers determine two independent properties of the names they declare: storage duration and linkage.
存储类型指示符 决定了 声明对象 的两个属性: 链接(linkage) 和 存储周期(storage duration)
linkage 链接
Linkage refers to the ability of an identifier (variable or function) to be referred to in other scopes.
标识符的linkage 属性是指 一个标识符(指向的对象)被其他地方使用的能力。
标识符的 linkage 属性,有三类。no linkage internal external linkage
no linkage.
The identifier can be referred to only from the scope it is in. All function parameters and all non-extern block-scope variables (including the ones declared static) have this linkage.
no linkage - 说明这个标识符不能被其他scope使用【即这个标识符 只能被它所在的那个scope 访问和使用】。即不具有linkage 能力。
这样的例子有,函数的参数,函数内部定义的 没有使用 extern 修饰的标识符。
static int add(int a, int b){ int c = a+b; return c; }
a, b c 只 在 add 这个函数内有效。其他地方出现的 a,b,c 和这儿的a,b,c无任何关系。
internal linkage.
The identifier can be referred to from all scopes in the current translation unit. All static file-scope identifiers (both functions and variables) have this linkage.
internal linkage - 说明这个标识符 只能被它所在的那个翻译单元(可以理解为 它所在的 .c 文件) 内的其他 scope 内(比如其他函数内),访问和使用。即 具有 翻译单元内 的 linkage 能力。
这样的例子有 .c 文件中,具有文件作用域的(即不在任何 { } 内的),被static 修饰的标识符。
static int age = 5; static int add(int a, int b);
age add 这两个标识符只在 本.c 文件中有效。本.c 文件中,所有地方出现的 age add 都指的是同一个 age add 。
external linkage.
The identifier can be referred to from any other translation units in the entire program. All non-static functions, all extern variables (unless earlier declared static), and all file-scope non-static variables have this linkage.
external linkage - 说明这个标识符 能被它所在的 程序 的其他 scope 内(比如 其他 .c 文件中的 函数内),访问和使用。即 具有 整个程序 内 的 linkage 能力。
这样的例子有 .c 文件中,具有文件作用域的(即不在任何 { } 内的),没有被static 修饰的,和 被 external 修饰的 标识符。
int age = 5; int add(int a, int b); extern char * name = “zhiwei.zhang”;
age add name 这几个 标识符 在 整个程序 中 有效。整个程序中,所有地方出现的 age add name都指的是同一个 age add name.
storage duration 存储周期
Every object has a property called storage duration, which limits the object lifetime. There are four kinds of storage duration in C:
每个对象具有 存储周期 这一个属性,这个属性决定了对象的生命周期。有 4 种类型的存在周期:
automatic storage duration 自动存储周期
The storage is allocated when the block in which the object was declared is entered and deallocated when it is exited by any means (goto, return, reaching the end). One exception is the VLAs; their storage is allocated when the declaration is executed, not on block entry, and deallocated when the declaration goes out of scope, not when the block is exited (since C99). If the block is entered recursively, a new allocation is performed for every recursion level. All function parameters and non-static block-scope objects have this storage duration, as well as compound literals used at block scope.
自动储存周期: 标识符 指向对象的存储空间 在进入 块作用域 时被分配,退出 块作用域时被释放。
例外是 变长数组 类型的标识符。它指向的对象 在 标识符声明的未知被 分配,在标识符作用域退出时是否。
递归进入时,每进入一次,储存空间分配一次。
函数参数,函数内 声明的 ,没有被 static 修饰的对象,块作用域内的复合字面量(compound literals) 都属于这种 存储周期 类型。
static storage duration. 静态存储周期
The storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function. All objects declared static and all objects with either internal or external linkage that aren't declared _Thread_local (since C11) have this storage duration.
存储空间在整个程序执行期间都存在。
在main 函数进入之前对象已经被初始化。
被static 修饰对象;具有 internal likage 或 external linkage 但是没有被 _Thread_local 修饰的对象 都属于此类。
thread storage duration 线程存储周期
The storage duration is the entire execution of the thread in which it was created, and the value stored in the object is initialized when the thread is started. Each thread has its own, distinct, object. If the thread that executes the expression that accesses this object is not the thread that executed its initialization, the behavior is implementation-defined. All objects declared _Thread_local have this storage duration. (since C11)
线程运行期间存储空间存在,线程启动之前 存储空间被初始化。
执行 对象 初始化 的线程 和 执行对象 读写的 线程不是同一个时,行为由编译器实现定义。
被 _Thread_local 修饰的对象,具有 线程存储周期。
allocated storage duration 动态分配存储周期
The storage is allocated and deallocated on request, using dynamic memory allocation functions.
使用 动态内存分配 函数申请和释放的对象。
storage-class specifier 逐个说明
auto - automatic duration and no linkage。
被auto 存储类型限定的 标识符 ,具有 none linkage ,具有automatic duration
说明:
通常,函数块作用域内的 即没有被 static 修饰,又每当有被 extern修饰 的标识符 ,才具有 none linkage。 在这种情况下,不使用auto 修饰,和时有auto 修饰 的一样的了。所以,我们一般不会看到 auto 这个 storage-class specifier 的使用。
int add(int a, int b){ int c ; // 或者 int auto c ; auto 只能使用在这儿, //但是这儿不使用auto,标识符指向的对象 //也是 no linkage 和 automatic duration c = a+b; return c; }
register - automatic duration and no linkage; address of this variable cannot be taken
1、只能修饰 函数块内 声明的标识符。具有 no linkage 属性和automatic duration。
2、被修饰的 标识符,不能取其地址。
static - static duration and internal linkage (unless at block scope)
静态存储周期 internal linkage ( 除非出现的 函数块作用域 内部(这时具有 none linkage)属性 )
extern - static duration and external linkage (unless already declared internal)
静态存储周期 external linkage ( 除非之前已经被 static 修饰了(这时,具有 internal linkage) )
_Thread_local - thread storage duration (since C11)
线程存储周期,【 linkage 属性由 static / extern 来决定】