C
C 语法

External and tentative definitions

外部和暂定的定义

在翻译单元的顶层(即预处理程序之后包含所有#includes 的源文件),每个 C 程序都是一系列声明,声明具有外部链接的函数和对象。这些声明被称为外部声明,因为它们出现在任何函数之外。

extern int n; // external declaration with external linkage int b = 1; // external definition with external linkage static const char *c = "abc"; // external definition with internal linkage int f(void) { // external definition with external linkage int a = 1; // non-external return b; } static void x(void) { // external definition with internal linkage }

使用外部声明声明的对象具有静态存储持续时间,因此不能使用autoregister指定符。由外部声明引入的标识符具有文件范围。

暂定义

暂定定义为外部声明没有初始化,并且或者没有存储类说明或与说明符static

一个初步的定义是,可能会或可能不会作为一个定义的声明。如果在同一翻译单元中早或晚时发现实际的外部定义,那么暂定义只是作为声明。

int i1 = 1; // definition, external linkage int i1; // tentative definition, acts as declaration because i1 is defined extern int i1; // declaration, refers to the earlier definition extern int i2 = 3; // definition, external linkage int i2; // tentative definition, acts as declaration because i2 is defined extern int i2; // declaration, refers to the external linkage definition

如果在同一翻译单元中没有定义,那么暂定义定义就像初始化程序= 0(或者对于数组类型= {0})的实际定义一样。

int i3; // tentative definition, external linkage int i3; // tentative definition, external linkage extern int i3; // declaration, external linkage // in this translation unit, i3 is defined as if by "int i3 = 0;"

与 extern 声明不同,如果前一个声明确定了标识符的链接,那么暂定义可能与另一个同一标识符声明不相关。如果同一个标识符的两个声明在范围内并且具有不同的链接,则行为是未定义的:

static int i4 = 2; // definition, internal linkage int i4; // Undefined behavior: linkage disagreement with previous line extern int i4; // declaration, refers to the internal linkage definition static int i5; // tentative definition, internal linkage int i5; // Undefined behavior: linkage disagreement with previous line extern int i5; // refers to previous, whose linkage is internal

内部联系的初步定义必须具有完整的类型。

static int i[]; // Error, incomplete type in a static tentative definition int i[]; // OK, equivalent to int i[1] = {0}; unless redeclared later in this file

一个定义规则

每个翻译单元可以具有内部连接(static全局)的每个标识符的零或一个外部定义。

如果在非 VLA(自C99以来),sizeof 或 alignof(自C11以来)以外的任何表达式中使用具有内部链接的标识符,则翻译单元中该标识符必须有且仅有一个外部定义。

整个程序可能具有零或一个外部定义,每个标识符(除了内联函数外)(自C99以来)都带有外部链接。

如果除了非 VLA(自C99以来),sizeof 或 alignof(自C11以来)之外的任何表达式中使用带有外部链接的标识符,则整个程序中某处必须有唯一的外部定义。

笔记

有关内联函数定义的详细信息,请参阅内联。

extern使用文件范围声明查看关键字含义的存储持续时间和链接。

请参阅声明和定义之间区别的定义。

为了标准化各种 C89之前的方法,我们发明了暂时的定义,以通过内部链接转发声明标识符。

参考

  • C11 standard (ISO/IEC 9899:2011):