C Extern声明在同一范围内遵循非Extern声明 #包括 外部INTX; int main() { int x; x=1; printf(“%d”,x); } #包括 int main() { 外部INTX; int x; x=1; printf(“%d”,x); }
我正在学习C Extern声明在同一范围内遵循非Extern声明 #包括 外部INTX; int main() { int x; x=1; printf(“%d”,x); } #包括 int main() { 外部INTX; int x; x=1; printf(“%d”,x); },c,variables,extern,C,Variables,Extern,我正在学习extern关键字,有人告诉我extern这个词用于声明变量,编译器不会为此变量分配。 但是当我写两个代码时,第一个代码正常运行,第二个代码出错。 请帮我解释一下为什么会有这种差异。谢谢。同一范围内有冲突的声明 当extern intx时出现在函数外部,它在文件范围内声明x。然后,当intx出现在函数内部,它声明了一个新的x实例,该实例与先前的extern int x无关。这是C语言允许的,因此编译器不会对此抱怨 当extern intx时出现在函数内部,它在块范围内声明x。然后,当i
extern
关键字,有人告诉我extern
这个词用于声明变量,编译器不会为此变量分配。
但是当我写两个代码时,第一个代码正常运行,第二个代码出错。
请帮我解释一下为什么会有这种差异。谢谢。同一范围内有冲突的声明
当extern intx时代码>出现在函数外部,它在文件范围内声明x
。然后,当intx
出现在函数内部,它声明了一个新的x
实例,该实例与先前的extern int x无关代码>。这是C语言允许的,因此编译器不会对此抱怨
当extern intx时代码>出现在函数内部,它在块范围内声明x
。然后,当intx代码>出现在它之后,它试图在同一范围内声明不同的x
。这是C标准不允许的,因此编译器会报告一个错误
extern
关键字在这里并不特别相关。错误是由相同标识符的两个冲突声明引起的。例如:
#include <stdio.h>
int main()
{
extern int x;
int x;
x = 1;
printf("%d", x);
}
关于声明的规则
由于C语言的发展历史,有关C语言声明的规则存在一些不规范之处。在文件范围内考虑这些声明:
char c;
int main(void)
{
char d;
int c; // Allowed, new declaration in new scope.
int d; // Not allowed, conflicting declaration in same scope.
}
第一个声明做(或不做)几件事:
- 它表示
x
是int
的标识符
- 它表示
x
具有外部链接,这意味着可以(在对象模块链接期间)引用在其他地方声明的名为x
的对象
- 它不定义
int
第二次声明:
- 它表示
x
是int
的标识符
- 它表示
x
具有外部链接(因为对于没有存储类说明符(如static
external函数)的对象,external是默认的声明)
- 它定义了一个
int
。(这实际上是一个暂定的定义,但我们在此不讨论。)
这两个声明都表示x
是int
的标识符,并且具有外部链接。它们之间的区别是第一个不定义对象(它只是说x
是在其他地方定义的对象的名称),第二个定义了int
(因此它是在其他地方定义的)。因此,这些声明不冲突,是允许的
另一方面,考虑函数中的这些声明。然后它们在块范围内
然后extern intx
与上面的含义相同:x
是一个标识符,具有在别处定义的对象的外部链接
但是intx代码>具有不同的含义。它不是说x
有外部(或内部)链接,而是说x
没有链接,因为块范围中的声明默认没有链接。这就产生了冲突,因为C 2018 6.7 3规定,除了带有特定条件的typedef
名称和标签外,没有链接的标识符不得在同一范围内声明多次(以及名称空间,此处未提及)
范围
C有四种作用域:
- 文件作用域用于函数之外的声明,并持续到正在编译的源文件的末尾
- 块作用域用于函数内的声明,并持续到块结束(下面讨论)
- 函数原型作用域用于函数原型参数中的声明。(例如,在
void foo(int n,float a[n][n]);
,n
和a
具有函数原型范围。)
- 功能范围用于
goto
语句中使用的标签
复合语句是{
和}
中声明和语句的列表。每个复合语句都是一个块,它为声明创建一个新的作用域。一个函数的主体是一个复合语句,它是一个块,它可能有额外的复合语句在其中,每个语句都开始一个新的作用域
块也是由switch
、if
、do
、while
和for
语句创建的,但它们对于前四个语句基本上不重要,因为只有for
语句提供了进一步声明的机会。例如,在For
语句中,您可以编写For(int x=3;x<20;++x)
,这将创建x
的一个新实例,因为For
语句启动一个新块。在同一范围内有冲突的声明
当extern intx时代码>出现在函数外部,它在文件范围内声明x
。然后,当intx
出现在函数内部,它声明了一个新的x
实例,该实例与先前的extern int x无关代码>。这是C语言允许的,因此编译器不会对此抱怨
当extern intx时代码>出现在函数内部,它在块范围内声明x
。然后,当intx代码>出现在它之后,它试图在同一范围内声明不同的x
。这是C标准不允许的,因此编译器会报告一个错误
extern
关键字在这里并不特别相关。错误是由相同标识符的两个冲突声明引起的。例如:
#include <stdio.h>
int main()
{
extern int x;
int x;
x = 1;
printf("%d", x);
}
关于声明的规则
关于C声明的规则由于t而存在一些不规则之处
extern int x;
int x;