首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

External and tentative definitions

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

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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})的实际定义一样。

代码语言:javascript
复制
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 声明不同,如果前一个声明确定了标识符的链接,那么暂定义可能与另一个同一标识符声明不相关。如果同一个标识符的两个声明在范围内并且具有不同的链接,则行为是未定义的:

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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):
    • 6.9 External definitions (p: 155-159)
  • C99 standard (ISO/IEC 9899:1999):
    • 6.9 External definitions (p: 140-144)
  • C89/C90 standard (ISO/IEC 9899:1990):
    • 3.7 EXTERNAL DEFINITIONS

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com