3

天真地认为它有,因为通常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;

在没有任何存储类关键字的情况下声明x并编译:

#include <stdio.h>

int x;

int main(void){
  x = 7;
  printf("x = %d", x);
}

现在我想知道x上面示例中的存储类是什么?它有名字吗?

4

3 回答 3

7

关键字auto, static, extern, register, 和_Thread_local在标准中被称为存储类说明符,但“对象”(这是我们通常称为“变量”的标准术语)没有存储类。相反,它们具有链接(外部、内部、无)和存储持续时间(静态、自动、线程)。此外,对象的任何声明可能是也可能不是定义。存储类说明符与声明对象的范围以及它是否具有初始化程序 ( int foovs int foo = 3) 一起控制这些属性。最简单的方法是展示它是如何与表格一起工作的:

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

术语“存储类说明符”有意与术语“存储持续时间”和“链接”不同,以提醒您说明符不会让您独立控制存储持续时间和链接。

该语言无法让您独立控制存储持续时间、链接和定义,因为不可用的组合没有意义。自动存储持续时间仅对在块范围内声明的变量有意义,而不是定义仅对具有外部链接的变量有意义(因为只有它们可以在另一个文件中定义)等等。

我离开了桌子register_Thread_local因为它们很特别。 register就像auto除了它也意味着您不允许获取对象的地址。 _Thread_local使变量的存储时间为“线程”并且不改变链接;它可以单独使用,也可以与externor一起使用static,但将其与“auto”结合使用是违反约束的。如果您在块范围内单独使用它,我不确定它会做什么。

于 2019-02-12T20:57:52.593 回答
4

从 C 标准 § 6.2.4 第 3 段:

一个对象,其标识符在没有存储类说明符 _Thread_local 的情况下声明,并且具有外部或内部链接或存储类说明符 static,具有静态存储持续时间。它的生命周期是程序的整个执行过程,它的存储值只在程序启动之前初始化一次。

强调我的。反向参考 § 6.2.2 第 5 段:

如果函数标识符的声明没有存储类说明符,则它的链接将完全确定,就好像它是使用存储类说明符 extern 声明的一样。如果对象标识符的声明具有文件范围且没有存储类说明符,则其链接是 external

再次强调我的。

因此,全局变量默认具有静态存储持续时间。即使没有标准来保证这一点,它也是唯一对全局变量有意义的存储持续时间类型。

于 2019-02-12T20:34:15.940 回答
3

每个变量在 C 中都有一个存储类吗?

是的,尽管该标准实际上为此使用了“存储持续时间”一词。这是同一件事,而且标准对关键字 , 等使用术语“存储类说明符”有些auto不一致static

天真地认为它有,因为通常在未提供存储类关键字时假定为 auto。

不,绝对不是。默认值extern适用于函数和在文件范围内声明的任何内容。只有在块范围内声明的对象的标识符默认为auto.

尽管如此,对于文件范围的变量,在它们前面放置一个 auto 会产生错误。

正如它应该。该标准明确规定

存储类说明符autoregister不应出现在外部声明的声明说明符中。

[C11,第 6.9/2 段]

在没有任何存储类关键字的情况下声明 x 并编译 [....]

当然。

现在我想知道上面示例中的存储类 x 是什么?它有名字吗?

它的存储类是关键字对应的存储类extern。正如我已经说过的,这是文件范围声明的默认设置。但是,尽管该标准使用术语“存储类说明符”,但它并没有将“存储类”作为一个独立的概念使用。它说话而不是 storage duration。所有具有外部或内部链接的变量都具有静态存储持续时间,这意味着它们在程序的整个生命周期中都存在。

于 2019-02-12T20:42:36.700 回答