C 中的 extern 关键字是多余的吗?
Is extern keyword in C redundant?
我发现我可以在不使用 extern 的情况下获得预期的结果(尽管我同意它给了 reader 某种关于变量的提示)。在某些情况下,使用 extern 会产生意想不到的结果。
xyz.h
int i;
file1.c
#include "xyz.h"
....
i=10;
....
file2.c
#include "xyz.h"
main()
{
printf("i=%d\n",i);
}
当然是个大工程,分解一下简单理解一下。使用 extern 关键字,我无法获得想要的结果。事实上,我使用 "extern" 方法得到变量 i 的链接器错误。
代码采用 "extern" 方法,
file1.c
int i;
main()
{
i=10;
}
file2.c
extern int i;
foo()
{
printf("i=%d\n",i);
}
这导致链接器错误。我只是想知道为什么它在第一种情况下有效,以及在不使用关键字 "extern" 的情况下我们无法做到这一点的实际情况。谢谢。
形式上,您的第一个程序无效。在头文件中定义一个变量,然后将这个头文件包含到多个翻译单元中,最终将导致具有外部链接的同一实体的多个定义。这是 C 中的约束违规。
6.9 External definitions
5 An external definition is an external declaration that is also a
definition of a function (other than an inline definition) or an
object. If an identifier declared with external linkage is used in an
expression (other than as part of the operand of a sizeof operator
whose result is an integer constant), somewhere in the entire program
there shall be exactly one external definition for the identifier;
otherwise, there shall be no more than one.
第一个示例中 i
的定义是 暂定定义 (正如评论中提到的那样),但它变成了一个常规的完整定义外部定义 of i
在包含头文件的每个翻译单元的末尾。因此,从 "whole program" 的角度来看,该定义的 "tentativeness" 没有任何改变。这与手头的事情并没有真正的关系(除了下面的一点评论)。
使您的第一个示例无误编译的原因是流行的编译器扩展,甚至在语言标准中也提到了这一点。
J.5 Common extensions
J.5.11 Multiple external definitions
1 There may be more than one
external definition for the identifier of an object, with or without
the explicit use of the keyword extern; if the definitions disagree,
or more than one is initialized, the behavior is undefined (6.9.2).
(最初导致 C 中的编译器扩展的原因很可能是暂定定义支持的一些实现特性,但在抽象语言级别暂定定义与此无关。)
你的第二个程序对于 i
是有效的(顺便说一句,C 中不再支持隐式 int
)。我不明白你怎么能从中得到任何链接器错误。
至少有 2 种情况 extern
有意义而不是 "redundant":
对于文件作用域的对象(不是函数),它声明了具有外部链接的对象,而不提供暂定定义;暂定定义在翻译单元末尾变成完整定义,不允许在多个翻译单元中使用外部链接定义相同的标识符。
在块作用域(在函数中),extern
允许您声明和访问具有外部链接的对象或函数,而无需将标识符带入文件作用域(因此它在外部不可见带有声明的块)。如果名称可能与文件范围内的其他内容冲突,这将很有用。例如:
static int a;
int foo(void)
{
return a;
}
int bar(void)
{
extern int a;
return a;
}
如果bar
中没有extern
关键字,int a;
会产生一个局部变量(自动存储)。
我发现我可以在不使用 extern 的情况下获得预期的结果(尽管我同意它给了 reader 某种关于变量的提示)。在某些情况下,使用 extern 会产生意想不到的结果。
xyz.h
int i;
file1.c
#include "xyz.h"
....
i=10;
....
file2.c
#include "xyz.h"
main()
{
printf("i=%d\n",i);
}
当然是个大工程,分解一下简单理解一下。使用 extern 关键字,我无法获得想要的结果。事实上,我使用 "extern" 方法得到变量 i 的链接器错误。
代码采用 "extern" 方法,
file1.c
int i;
main()
{
i=10;
}
file2.c
extern int i;
foo()
{
printf("i=%d\n",i);
}
这导致链接器错误。我只是想知道为什么它在第一种情况下有效,以及在不使用关键字 "extern" 的情况下我们无法做到这一点的实际情况。谢谢。
形式上,您的第一个程序无效。在头文件中定义一个变量,然后将这个头文件包含到多个翻译单元中,最终将导致具有外部链接的同一实体的多个定义。这是 C 中的约束违规。
6.9 External definitions
5 An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
第一个示例中 i
的定义是 暂定定义 (正如评论中提到的那样),但它变成了一个常规的完整定义外部定义 of i
在包含头文件的每个翻译单元的末尾。因此,从 "whole program" 的角度来看,该定义的 "tentativeness" 没有任何改变。这与手头的事情并没有真正的关系(除了下面的一点评论)。
使您的第一个示例无误编译的原因是流行的编译器扩展,甚至在语言标准中也提到了这一点。
J.5 Common extensions
J.5.11 Multiple external definitions
1 There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
(最初导致 C 中的编译器扩展的原因很可能是暂定定义支持的一些实现特性,但在抽象语言级别暂定定义与此无关。)
你的第二个程序对于 i
是有效的(顺便说一句,C 中不再支持隐式 int
)。我不明白你怎么能从中得到任何链接器错误。
至少有 2 种情况 extern
有意义而不是 "redundant":
对于文件作用域的对象(不是函数),它声明了具有外部链接的对象,而不提供暂定定义;暂定定义在翻译单元末尾变成完整定义,不允许在多个翻译单元中使用外部链接定义相同的标识符。
在块作用域(在函数中),
extern
允许您声明和访问具有外部链接的对象或函数,而无需将标识符带入文件作用域(因此它在外部不可见带有声明的块)。如果名称可能与文件范围内的其他内容冲突,这将很有用。例如:static int a; int foo(void) { return a; } int bar(void) { extern int a; return a; }
如果
bar
中没有extern
关键字,int a;
会产生一个局部变量(自动存储)。