在某些情况下,局部变量可以声明为 extern
让我们来读一下C99 N1256标准草案 http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf.
该标准将“局部变量”称为具有“块作用域”。
6.7.1/5“存储类说明符”说:
具有块作用域的函数的标识符声明不应具有除 extern 之外的显式存储类说明符。
那么添加意味着什么extern
对于局部变量,6.2.2/4“标识符的链接”说:
对于在该标识符的先前声明可见的范围内使用存储类说明符 extern 声明的标识符,如果先前的声明指定内部或外部链接,则后面声明处的标识符的链接与该链接相同在事先声明中指定。如果没有可见的先前声明,或者如果先前声明未指定链接,则该标识符具有外部链接。
让我们来分解一下这些案例。
没有事先声明
void f() {
extern int i;
}
是相同的:
extern int i;
void f() {}
除了该声明仅在内部可见f
.
这是因为i
没有可见的事先声明。所以i
具有外部链接(与全局变量相同的链接)。
事先声明未指定任何联系
int i;
void f() {
extern int i;
}
是相同的:
void f() {
extern int i;
}
因为事先声明int i
没有指定任何链接,因为第 6 段说:
以下标识符没有链接:声明为对象或函数以外的任何标识符;声明为函数参数的标识符;未使用存储类说明符 extern 声明的对象的块作用域标识符。
事先声明指定内部或外部链接
extern int i;
void f() {
extern int i;
}
是相同的:
extern int i;
void f() {}
and:
static int i;
void f() {
extern int i;
}
是相同的:
static int i;
void f() {}
因为在这两种情况下我们都有先前可见的外部和内部(static
) 分别链接声明。
初始化本地外部
无效C:
void f() {
extern int i = 0;
}
因为块作用域声明有一个初始化。
Valid C:
extern int i = 0;
void f() {}
但可以说是糟糕的风格,因为相当于较短的:
int i = 0;
void f() {}
因为 6.7.8 初始化说:
如果标识符的声明具有块作用域,并且标识符具有外部或内部链接,则声明不应具有标识符的初始值设定项。