c - 为什么 'extern'存储类的功能不同?

标签 c extern storage-class-specifier

下面的代码片段工作正常

extern int i;
int i;

int main(){
    return 0;
}

这里我得到的是,'i'被声明然后定义。由于只有一个定义,所以完全没问题。

int main(){
    extern int i;
    int i;
    return 0;
}

现在,上面的给出了以下错误

new.cpp: In function ‘int main()’:
new.cpp:5:6: error: redeclaration of ‘int i’
  int i;
      ^
new.cpp:4:13: note: previous declaration ‘int i’
  extern int i;

这里有什么问题吗?这里也有“i”的单一定义。

最佳答案

要理解其中的差异,您需要熟悉 C 中一个称为“暂定定义”的概念。引用 C 标准:

C11,草案,§6.9.2,外部对象定义

A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

第一个代码段中的内容只是 i 的暂定定义。您可以为一个对象拥有任意多个临时定义(但只允许一个定义):

int i; // tentative definition
int i; // tentative definition
int i; // tentative definition

int main(void) {
   return 0;
}

有效。

此处,i 具有外部链接且暂定定义。如果 i 是在同一翻译单元的某个地方定义的,那么这将是 i 的实际定义。如果在翻译单元中没有找到 i 的其他定义,那么这将成为完整的定义,就好像它的定义如下:

int i = 0;

int main(void) {
   return 0;
}

但是第二个片段int i;不是一个暂定定义。只能暂时定义具有外部链接的对象。在第二个片段中,声明 extern int i; 表示 i 是在其他地方通过外部链接定义的。但下一行 int i; 表示 i 是在没有链接的情况下定义的(局部自动变量没有任何链接 - 这不是暂定定义)。因此,i 的定义存在冲突。因此,第一个片段很好,但第二个片段则不然。

关于c - 为什么 'extern'存储类的功能不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32535793/

相关文章:

d - 什么是纯变量?

c++ - 外部存储类说明符

c - 开关盒 : error: case label does not reduce to an integer constant

Clang 无法在 C89 模式下对非常量数组初始值设定项抛出错误

c - 使用 extern(C) 的 swig D 绑定(bind)与现有的 extern(C) 函数冲突

c - extern 变量的用途?

c++ - 变量可以同时声明为静态和外部吗?

c - Newt 中的按钮

C 通过引用(指针)传递崩溃

C++ 全局外部 "C" friend 无法访问命名空间类上的私有(private)成员