在C中,我没有注意到在函数声明之前使用extern关键字的任何影响。
首先,我认为当定义extern int f();在单个文件中强制您在文件范围之外实现它。然而,我发现:
extern int f();
int f() {return 0;}
and
extern int f() {return 0;}
编译正常,没有来自gcc的警告。我使用gcc -Wall -ansi;它甚至不接受//注释。
在函数定义之前使用extern有什么影响吗?或者它只是一个可选的关键字,对函数没有副作用。
在后一种情况下,我不明白为什么标准设计师选择用多余的关键字乱扔语法。
编辑:为了澄清,我知道在变量中有extern的用法,但我只问函数中的extern。
extern关键字根据环境的不同有不同的形式。如果声明可用,则extern关键字采用前面在翻译单元中指定的链接。在没有任何此类声明的情况下,extern指定外部链接。
static int g();
extern int g(); /* g has internal linkage */
extern int j(); /* j has tentative external linkage */
extern int h();
static int h(); /* error */
以下是C99草案(n1256)的相关段落:
6.2.2 Linkages of identifiers
[...]
4 For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,23) if the prior declaration specifies internal or
external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external linkage.
5 If the declaration of an identifier for a function has no storage-class specifier, its linkage
is determined exactly as if it were declared with the storage-class specifier extern. If
the declaration of an identifier for an object has file scope and no storage-class specifier,
its linkage is external.
我们有两个文件,foo.c和bar.c。
这是foo.c
#include <stdio.h>
volatile unsigned int stop_now = 0;
extern void bar_function(void);
int main(void)
{
while (1) {
bar_function();
stop_now = 1;
}
return 0;
}
这是bar。c
#include <stdio.h>
extern volatile unsigned int stop_now;
void bar_function(void)
{
if (! stop_now) {
printf("Hello, world!\n");
sleep(30);
}
}
正如你所看到的,foo.c和bar.c之间没有共享头文件,但是bar.c在被链接时需要在foo.c中声明的东西,而foo.c在被链接时需要bar.c中的函数。
通过使用'extern',你告诉编译器,在链接时,它后面的任何内容都将被找到(非静态);不要在当前通道中为它保留任何东西,因为它将在以后遇到。函数和变量在这方面是平等对待的。
如果你需要在模块之间共享一些全局,而不想把它放在/初始化在一个头文件中,它是非常有用的。
从技术上讲,库公共标头中的每个函数都是“extern”,但根据编译器的不同,将它们标记为“extern”几乎没有任何好处。大多数编译器可以自己解决这个问题。如你所见,这些函数实际上是在其他地方定义的。
在上面的例子中,main()只打印一次hello world,但继续输入bar_function()。还要注意,bar_function()在本例中不会返回(因为这只是一个简单的示例)。想象一下stop_now在信号被服务时被修改(因此是volatile),如果这看起来不够实际的话。
对于信号处理程序、一个你不想放在头文件或结构中的互斥量等,extern非常有用。大多数编译器会优化以确保它们不为外部对象保留任何内存,因为它们知道它们将在定义对象的模块中保留内存。但是,同样,在创建公共函数原型时,使用现代编译器指定它没有什么意义。