我发现我可以在不使用extern的情况下达到预期的效果(尽管我同意它会给读者一些关于变量的暗示)。在某些情况下,使用extern会产生不良结果。
xyz.h
int i;
file1.c中
#include "xyz.h"
....
i=10;
....
file2.c中
#include "xyz.h"
main()
{
printf("i=%d\n",i);
}
当然,这是一个大项目,为了简单的理解而将其分解。使用extern关键字,我无法获得理想的结果。实际上,我的变量i的链接器错误是" extern"方法
代码" extern"方法,
file1.c中
int i;
main()
{
i=10;
}
file2.c中
extern int i;
foo()
{
printf("i=%d\n",i);
}
这给链接器错误。我只是想知道它为什么在第一种情况下工作,以及在不使用关键字" extern"我们无法做到的实际情况。感谢。
答案 0 :(得分:6)
正式地,您的第一个程序无效。在头文件中定义变量然后将该头文件包括到多个翻译单元中将最终导致具有外部链接的同一实体的多个定义。这是C中的约束违规。
6.9外部定义
5 外部定义是一个外部声明,也是一个 函数的定义(内联定义除外)或 宾语。如果使用外部链接声明的标识符 表达式(除了作为sizeof运算符的操作数的一部分之外) 其结果是整数常量),在整个程序中的某个地方 标识符只有一个外部定义; 否则,不得超过一个。
第一个示例中i
的定义是暂定定义(正如评论中提到的那样),但它变成了一个常规的完全成熟的外部定义的i
在每个包含头文件的翻译单元的末尾。所以,"暂定性"该定义并未改变整个计划的任何内容。观点看法。它与手头的事情并不紧密相关(除了下面的一点点评论)。
使你的第一个没有错误编译的例子是一个流行的编译器扩展,甚至在语言标准中也提到了这一点。
J.5常见扩展程序
J.5.11多个外部定义
1 可能不止一个 对象标识符的外部定义,有或没有 关键字extern的显式使用;如果定义不一致, 或者初始化多个行为,行为未定义(6.9.2)。
(最初导致C中编译器扩展的原因很可能是暂定定义支持的一些实现特性,但在抽象语言层面,暂定定义与此无关。)
您的第二个程序对i
有效(BTW,C中不再支持隐式int
)。我不知道你怎么能从它那里得到任何链接器错误。
答案 1 :(得分:1)
至少有两种情况extern
有意义而非“多余”:
对于文件范围内的对象(非函数),它声明具有外部链接的对象,而不提供暂定定义;暂定定义在翻译单元的末尾变成完整定义,并且不允许在多个翻译单元中使用外部链接定义相同的标识符。
在块范围内(在函数中),extern
允许您使用外部链接声明和访问对象或函数,而无需将标识符放入文件范围(因此它在块外部不可见宣言)。如果名称可能与文件范围内的其他名称冲突,这将非常有用。例如:
static int a;
int foo(void)
{
return a;
}
int bar(void)
{
extern int a;
return a;
}
如果extern
中没有bar
关键字,int a;
会产生一个本地变量(自动存储)。