不可以extern.但是可以在本地声明全局变量.
// file1.c
int Count;
// file2.c
void foo(void) {
extern int Count;
Count++;
}
Run Code Online (Sandbox Code Playgroud)
不可以.变量可能不是extern和register.
C11 dr 6.7.1存储类说明符
1 存储类说明符:
typedef
extern
static
_Thread_local
auto
register
约束
2最多可以在声明中的声明说明符中给出一个存储类说明符,但_Thread_local可能与staticor一起出现的除外extern)
可以将局部变量声明为extern吗?
是的,在某些情况下.
我们来看看C99 N1256标准草案.
该标准将"局部变量"称为具有"块范围".
6.7.1/5存储类说明符说:
具有块作用域的函数的标识符声明不应具有除extern之外的显式存储类说明符.
然后,对于添加extern到局部变量的含义,6.2.2/4标识符的链接说:
对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符,如果先前声明指定内部或外部链接,则后面声明中的标识符的链接与链接相同在先前的声明中指明.如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接.
让我们打破这些案件.
没有事先声明
void f() {
extern int i;
}
Run Code Online (Sandbox Code Playgroud)
是相同的:
extern int i;
void f() {}
Run Code Online (Sandbox Code Playgroud)
除了声明只在里面可见f.
这是因为i没有先前的声明可见.i外部链接也是如此(与全局变量相同的链接).
事先声明指定没有链接
void f() {
int i;
extern int i;
}
Run Code Online (Sandbox Code Playgroud)
是相同的:
void f() {
extern int i;
}
Run Code Online (Sandbox Code Playgroud)
因为先前的声明int i没有指定链接,因为第6段说:
以下标识符没有链接:声明为对象或函数以外的任何标识符; 声明为函数参数的标识符; 没有存储类说明符extern声明的对象的块作用域标识符.
事先声明指定内部或外部联系
extern int i;
void f() {
extern int i;
}
Run Code Online (Sandbox Code Playgroud)
是相同的:
extern int i;
void f() {}
Run Code Online (Sandbox Code Playgroud)
和:
static int i;
void f() {
extern int i;
}
Run Code Online (Sandbox Code Playgroud)
是相同的:
static int i;
void f() {}
Run Code Online (Sandbox Code Playgroud)
因为在这两种情况下,我们分别有一个先前可见的外部和内部(static)链接声明.
初始化本地外部
无效的C:
void f() {
extern int i = 0;
}
Run Code Online (Sandbox Code Playgroud)
因为块范围声明具有初始化.
有效C:
extern int i = 0;
void f() {}
Run Code Online (Sandbox Code Playgroud)
但可以说是糟糕的风格,因为相当于较短的:
int i = 0;
void f() {}
Run Code Online (Sandbox Code Playgroud)
因为6.7.8初始化说:
如果标识符的声明具有块作用域,并且标识符具有外部或内部链接,则声明不应具有标识符的初始化程序.
您只能将全局变量定义为extern. 告诉编译器(和链接器)它是在其他地方定义的。
局部变量仅存在于局部作用域中,因为它是在堆栈或寄存器中创建的。当执行不在范围内(不再)时,堆栈将展开(因此可用空间再次可用)或寄存器用于其他用途,并且变量(不再)存在。
因此,定义本地外部将是“奇怪的”且不可能的(由于堆栈的使用)。