a)外部变量的定义与局部变量的定义相同,即int i=2;
(仅在所有函数之外)。
但为什么extern int i=2;
也像定义一样工作?是不是extern
仅用于其他文件中的变量声明?
b)文件1
#include<stdio.h>
int i=3;
int main()
{
printf("%d",i);
fn();
}
file2的
int i; // although the declaration should be: extern int i; So, why is this working?
void fn()
{
printf("%d",i);
}
OUTPUT:两种情况下均为
答案 0 :(得分:5)
由于历史原因,确定联系的规则以及声明提供定义的时间有点混乱。
对于您的特定示例,在文件范围
extern int i = 2;
和
int i = 2;
是等效的外部定义,如果您提供初始化程序,则extern
是可选的。
但是,如果您不提供初始值设定项,则extern
不可选:
int i;
是具有外部链接的暂定定义,它成为等同于
的外部定义int i = 0;
如果翻译单元不包含具有显式初始化程序的其他定义。
这与
不同extern int i;
这绝不是一个定义。如果已经有另一个相同标识符的声明可见,那么变量将从中获得它的链接;如果这是第一个声明,变量将具有外部链接。
这意味着在第二个示例中,file1和file2都提供了i
的外部定义,这是未定义的行为,链接器可以自由选择它最喜欢的定义(它也可能尝试制作恶魔飞出你的鼻子)。 C有一个共同的扩展(见C99附件J.5.11和this question),这使得这个特殊情况得到了很好的定义。
答案 1 :(得分:1)
在C中,带有初始化的extern
会导致分配变量。这就是声明将被视为一个定义声明。这与extern
的更常见用法形成对比。
C标准说:
6.9.2外部对象定义
.....
如果对象的标识符声明具有文件范围和初始化程序,则 声明是标识符的外部定义。
至于问题的第二部分,文件范围内的声明int i
具有外部链接。如果要为其提供内部链接,则需要声明它static int i
。 C标准说:
6.2.2标识符的链接
...
如果对象的标识符声明具有文件范围而没有存储类说明符,则其链接是外部的。