每个变量在 C 中都有一个存储 class 吗?
Does every variable have a storage class in C?
天真地认为它有,因为通常在未提供存储 class 关键字时假定 auto
。
不过,对于文件范围的变量,在它们前面放置 auto
会产生错误。
#include <stdio.h>
auto int x;
int main(void){
x = 7;
printf("x = %d", x);
}
Clang 抱怨:
3:10: error: illegal storage class on file-scoped variable
auto int x;
在没有任何存储 class 关键字的情况下声明 x
并编译:
#include <stdio.h>
int x;
int main(void){
x = 7;
printf("x = %d", x);
}
现在我想知道在上面的例子中 class x
有什么存储空间?它有名字吗?
来自 C 标准 § 6.2.4 第 3 段:
An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
强调我的。反向引用 § 6.2.2 第 5 段:
If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
再次强调我的。
因此,全局变量默认具有静态存储期限。即使没有标准来保证这一点,它也是唯一对全局变量有意义的存储持续时间类型。
Does every variable have a storage class in C?
是的,尽管标准实际上为此使用了术语 "storage duration"。这是同一件事,而且标准对关键字 auto
、static
等使用术语 "storage class specifier" 也有些不一致。
Naively one could think it has, because usually auto is assumed when a storage class keyword is not supplied.
没有。绝对不。对于函数和在文件范围内声明的任何内容,默认值为 extern
。只有在块范围内声明的对象的标识符默认为 auto
.
Still, for file-scoped variables putting an auto in front of them gives an error.
应该的。该标准明确规定
The storage-class specifiers auto
and register
shall not appear in the declaration specifiers in an external declaration.
[C11, paragraph 6.9/2]
Declaring x without any storage class keyword and it compiles [....]
当然可以。
Now I wonder what storage class x has in the example above? Does it have a name?
它的存储class是关键字extern
对应的。正如我已经说过的,这是文件范围声明的默认设置。但是,尽管该标准使用了术语 "storage class specifier",但它并没有将 "storage class" 作为一个独立的概念使用。它说话而不是存储持续时间。所有具有外部或内部链接的变量都具有静态存储持续时间,这意味着它们在程序的整个生命周期中都存在。
关键字 auto
、static
、extern
、register
和 _Thread_local
在标准中称为 storage class 说明符,但是"objects"(这是我们通常所说的"variables" 的标准术语)没有存储classes。相反,它们具有 linkage(外部、内部、none)和 storage duration(静态、自动、线程)。此外,对象的任何声明可能是也可能不是定义。存储 class 说明符,以及声明对象的范围,以及它是否具有初始化程序(int foo
与 int foo = 3
)一起控制这些属性。使用 table:
可以最简单地展示它是如何工作的
sc-specifier scope initialized linkage storage duration is a definition
------------ ----- ----------- ------- ---------------- ---------------
auto file no [constraint violation]
auto file yes [constraint violation]
auto block no none automatic yes
auto block yes none automatic yes
none file no external static yes
none file yes external static yes
none block no none automatic yes
none block yes none automatic yes
static file no internal static yes
static file yes internal static yes
static block no none static yes
static block yes none static yes
extern file no external static no
extern file yes external static yes
extern block no external static no
extern block yes external static yes
术语 "storage class specifier" 有意不同于术语 "storage duration" 和 "linkage" 以提醒您说明符不会让您独立控制存储期限和链接。
该语言无法让您独立控制存储持续时间、链接和定义,因为不可用的组合没有意义。自动存储持续时间仅对在块范围内声明的变量有意义,而不是定义仅对具有外部链接的变量有意义(因为只有它们可以在另一个文件中定义),等等。
我将 register
和 _Thread_local
排除在 table 之外,因为它们很特殊。 register
就像 auto
一样,除了它还意味着您不能获取对象的地址。 _Thread_local
使变量的存储期限为 "thread" 并且不改变链接;它可以单独使用,也可以与 extern
或 static
一起使用,但将其与 "auto" 结合使用是违反约束的。如果您单独在块范围内使用它,我不确定它会做什么。
天真地认为它有,因为通常在未提供存储 class 关键字时假定 auto
。
不过,对于文件范围的变量,在它们前面放置 auto
会产生错误。
#include <stdio.h>
auto int x;
int main(void){
x = 7;
printf("x = %d", x);
}
Clang 抱怨:
3:10: error: illegal storage class on file-scoped variable
auto int x;
在没有任何存储 class 关键字的情况下声明 x
并编译:
#include <stdio.h>
int x;
int main(void){
x = 7;
printf("x = %d", x);
}
现在我想知道在上面的例子中 class x
有什么存储空间?它有名字吗?
来自 C 标准 § 6.2.4 第 3 段:
An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
强调我的。反向引用 § 6.2.2 第 5 段:
If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
再次强调我的。
因此,全局变量默认具有静态存储期限。即使没有标准来保证这一点,它也是唯一对全局变量有意义的存储持续时间类型。
Does every variable have a storage class in C?
是的,尽管标准实际上为此使用了术语 "storage duration"。这是同一件事,而且标准对关键字 auto
、static
等使用术语 "storage class specifier" 也有些不一致。
Naively one could think it has, because usually auto is assumed when a storage class keyword is not supplied.
没有。绝对不。对于函数和在文件范围内声明的任何内容,默认值为 extern
。只有在块范围内声明的对象的标识符默认为 auto
.
Still, for file-scoped variables putting an auto in front of them gives an error.
应该的。该标准明确规定
The storage-class specifiers
auto
andregister
shall not appear in the declaration specifiers in an external declaration.
[C11, paragraph 6.9/2]
Declaring x without any storage class keyword and it compiles [....]
当然可以。
Now I wonder what storage class x has in the example above? Does it have a name?
它的存储class是关键字extern
对应的。正如我已经说过的,这是文件范围声明的默认设置。但是,尽管该标准使用了术语 "storage class specifier",但它并没有将 "storage class" 作为一个独立的概念使用。它说话而不是存储持续时间。所有具有外部或内部链接的变量都具有静态存储持续时间,这意味着它们在程序的整个生命周期中都存在。
关键字 auto
、static
、extern
、register
和 _Thread_local
在标准中称为 storage class 说明符,但是"objects"(这是我们通常所说的"variables" 的标准术语)没有存储classes。相反,它们具有 linkage(外部、内部、none)和 storage duration(静态、自动、线程)。此外,对象的任何声明可能是也可能不是定义。存储 class 说明符,以及声明对象的范围,以及它是否具有初始化程序(int foo
与 int foo = 3
)一起控制这些属性。使用 table:
sc-specifier scope initialized linkage storage duration is a definition
------------ ----- ----------- ------- ---------------- ---------------
auto file no [constraint violation]
auto file yes [constraint violation]
auto block no none automatic yes
auto block yes none automatic yes
none file no external static yes
none file yes external static yes
none block no none automatic yes
none block yes none automatic yes
static file no internal static yes
static file yes internal static yes
static block no none static yes
static block yes none static yes
extern file no external static no
extern file yes external static yes
extern block no external static no
extern block yes external static yes
术语 "storage class specifier" 有意不同于术语 "storage duration" 和 "linkage" 以提醒您说明符不会让您独立控制存储期限和链接。
该语言无法让您独立控制存储持续时间、链接和定义,因为不可用的组合没有意义。自动存储持续时间仅对在块范围内声明的变量有意义,而不是定义仅对具有外部链接的变量有意义(因为只有它们可以在另一个文件中定义),等等。
我将 register
和 _Thread_local
排除在 table 之外,因为它们很特殊。 register
就像 auto
一样,除了它还意味着您不能获取对象的地址。 _Thread_local
使变量的存储期限为 "thread" 并且不改变链接;它可以单独使用,也可以与 extern
或 static
一起使用,但将其与 "auto" 结合使用是违反约束的。如果您单独在块范围内使用它,我不确定它会做什么。