全局范围内的外部关键字

问题描述 投票:0回答:1

根据有关存储类说明符的 c 文档(使用众所周知的 cpp 参考网站):https://en.cppreference.com/w/c/language/storage_duration,“存储类说明符出现在声明中.. ..如果未提供存储类说明符,则默认值为:

  1. 所有函数都使用 extern
  2. extern 用于文件范围内的对象
  3. 对于块范围内的对象为 auto”

因此,当我们在一个文件中定义了文件范围变量 i 时:

文件1.c

int i = 0;

如何在文件范围(在另一个文件中)同时具有(1)没有存储类说明符和(2)只有变量声明。因为如果没有 extern 关键字,则文件范围变量会被初始化和定义,因此似乎该变量只能被定义,从而导致编译器错误:

文件2.c

int i;

或用 extern 关键字声明:

文件2.c

extern int i;

因此,我不明白它们如何既是声明又在文件范围内没有存储类说明符。我可能对语义了解太多,但在文件范围内有一个默认为 extern 的默认声明是没有意义的。任何帮助将不胜感激!

c extern storage-class-specifier
1个回答
0
投票

[来自问题]...(使用众所周知的cpp参考网站)...

cppreference.com 不是 C 或 C++ 的权威参考,并且存在许多缺陷。当其中出现问题时,您应该参考C或C++标准。

[来自问题]“存储类说明符出现在声明中......如果未提供存储类说明符,则默认值为:...”

尽管您省略的文本说“存储类说明符确定它们声明的名称的两个独立属性:存储持续时间链接”,但这段文字的构造是为了给人(不正确的)印象:如果没有存储类提供了说明符,其语义就好像它列出的默认值之一是作为存储类说明符提供的。

那是错误的。在各种情况下,不带任何存储类说明符的声明的语义与具有存储类说明符的声明存在差异。

int i;
出现在文件范围内时,它具有静态存储持续时间和外部链接,就像使用了
extern int i;
一样。然而,它们的不同之处在于,
int i;
暂定定义,而
extern int i;
声明

请注意,尽管顾名思义,暂定定义实际上并不是定义,就像求职面试中的潜在雇员不是雇员一样。

int i;
是声明,不是定义。

考虑一个翻译单元包含:

int i;
int i;
int i = 3;
int i;

在这种情况下,

int i = 3;
是一个定义,暂定定义除了作为声明之外没有任何作用。它们的语义受声明规则的约束,C 标准中没有任何内容表明它们是
i
的定义。

或者,考虑:

int i;
int i;
int i;

在这种情况下,这些暂定定义又是声明,但 C 2018 6.9.2 2 告诉我们,实际上,在翻译单元的末尾为

i
创建了定义:

[C 2018 6.9.2 2] ...如果翻译单元包含标识符的一个或多个暂定定义,并且翻译单元不包含该标识符的外部定义,则行为就像翻译单元包含文件范围一样该标识符的声明,具有翻译单元末尾的复合类型,初始值设定项等于 0。

[来自问题]在文件范围(在另一个文件中)如何可能同时具有(1)没有存储类说明符和(2)只有变量的声明。

int i;

 没有存储类说明符,是一个声明,而不是定义。它的行为方式受 C 2018 6.9.2 2 中的规则管辖;它的行为方式与 
extern int i;
int i = 0;
 不同。

[来自标题]全局范围内的外部关键字

C 没有全局作用域。它有文件范围,这是不同的。在具有全局作用域的编程语言中,在全局作用域声明标识符可以使其在整个程序中被识别。在 C 中,在文件范围声明标识符使其仅在声明的翻译单元中已知,而不是在整个程序中已知。为了让程序中的其他地方知道它,必须在其他地方声明并链接。

© www.soinside.com 2019 - 2024. All rights reserved.