我的问题是什么时候一个函数应该引用extern关键字在C。

我看不出什么时候应该在实践中使用这种方法。当我在编写程序时,我使用的所有函数都可以通过我包含的头文件获得。那么,extern访问头文件中没有公开的内容为什么有用呢?

我可能在想extern如何不正确地工作,如果是这样,请纠正我。

也. .当它是头文件中没有关键字的默认声明时,您是否应该扩展某些内容?


当你在不同的dll或lib上定义该函数时,编译器会根据链接器来查找它。典型的情况是当你从OS API调用函数时。

如果程序中的每个文件首先被编译为一个目标文件,然后目标文件被链接在一起,则需要extern。它告诉编译器“这个函数存在,但是它的代码在其他地方。不要惊慌。”

Extern更改链接。使用关键字,函数/变量被假定在其他地方可用,解析被推迟到链接器。

函数上的extern和变量上的extern是不同的。

对于变量,它不实例化变量本身,即不分配任何内存。这得在别的地方做。因此,如果您想从其他地方导入变量,这是很重要的。

对于函数,这只告诉编译器链接是extern。因为这是默认值(使用关键字static表示函数没有使用extern链接绑定),所以不需要显式地使用它。

在其他源文件中实际定义的函数应该只在头文件中声明。在这种情况下,在头文件中声明原型时应该使用extern。

大多数情况下,你的函数会是以下其中之一(更像是最佳实践):

静态(不是静态的普通函数 可见的外部。c文件) 静态内联(内联来自。c或。h 文件) 的头中的声明 下一类(见下文)) [no关键字whatever](正常 用于访问的函数 外面的声明)

头文件中所有函数和变量的声明都应该是extern。

该规则的例外是头文件中定义的内联函数和变量,尽管在头文件中定义,但它们必须是翻译单元的本地变量(头文件包含的源文件):这些应该是静态的。

在源文件中,extern不应该用于文件中定义的函数和变量。只需要为本地定义加上静态前缀,而不需要为共享定义做任何事情——默认情况下,它们将是外部符号。

在源文件中使用extern的唯一原因是声明在其他源文件中定义且没有提供头文件的函数和变量。


声明函数原型extern实际上是不必要的。有些人不喜欢它,因为它只会浪费空间,而且函数声明已经有溢出行限制的倾向。其他人喜欢它,因为这样,函数和变量可以以相同的方式处理。

在C语言中,函数原型隐含了extern,因为原型声明了在其他地方定义的函数。换句话说,函数原型默认具有外部链接;使用extern很好,但这是多余的。

(如果需要静态链接,函数必须在它的原型和函数头中都声明为静态的,并且它们通常都应该在同一个.c文件中)。

前面已经说过,extern关键字对于函数来说是多余的。

对于跨编译单元共享的变量,应该在头文件中使用extern关键字声明它们,然后在单个源文件中定义它们,不使用extern关键字。为了最佳实践,单个源文件应该是共享头文件名称的文件。

Extern告诉编译器这个数据是在某个地方定义的,并且将与链接器连接。

在这里的回答和与一些朋友的交谈的帮助下,这里有一个使用extern的实际示例。

例1 -显示一个陷阱:

stdio . h:

int errno;

myCFile1.c:

#include <stdio.h>

// Code using errno...

myCFile2.c:

#include <stdio.h>

// Code using errno...

如果myCFile1。o和myCFile2。O是链接的,每个c文件都有单独的errno副本。这是一个问题,因为相同的errno应该在所有链接的文件中可用。

例2 -修复。

stdio . h:

extern int errno;

stdio.c:

int errno;

myCFile1.c:

#include <stdio.h>

// Code using errno...

myCFile2.c:

#include <stdio.h>

// Code using errno...

如果两者都是myCFile1。o和MyCFile2。O由链接器链接,它们都指向相同的errno。因此,用extern解决实现问题。

一篇关于extern关键字的非常好的文章,以及示例:http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

虽然我不同意在函数声明中使用extern是多余的。这应该是一个编译器设置。因此,我建议在需要时在函数声明中使用extern。

多年以后,我发现了这个问题。看完每个回答和评论后,我想我可以澄清一些细节……这可能对通过谷歌搜索来到这里的人有用。

这个问题是专门关于使用extern函数的,所以我将忽略对全局变量使用extern。

让我们定义3个函数原型:

// --------------------------------------
// Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
       int function_3(void);

头文件可以被主要源代码使用,如下所示:

// --------------------------------------
// Filename: "my_project.C"
#include "my_project.H"

void main(void) {
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 1234;

为了编译和链接,我们必须在调用function_2的源代码文件中定义function_2。另外两个函数可以在不同的源代码*. c中定义,也可以位于任何二进制文件(*. c)中。OBJ, *。LIB, *. dll),我们可能没有源代码。

让我们再次将my_project.H头文件包含在不同的*. c文件中,以便更好地理解两者的区别。在同一个项目中,我们添加以下文件:

// --------------------------------------
// Filename: "my_big_project_splitted.C"
#include "my_project.H"

void old_main_test(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 5678;

int function_1(void) return 12;

int function_3(void) return 34;

需要注意的重要特性:

When a function is defined as static in a header file, the compiler/linker must find an instance of a function with that name in each module which uses that include file. A function which is part of the C library can be replaced in only one module by redefining a prototype with static only in that module. For example, replace any call to malloc and free to add memory leak detection feature. The specifier extern is not really needed for functions. When static is not found, a function is always assumed to be extern. However, extern is not the default for variables. Normally, any header file that defines variables to be visible across many modules needs to use extern. The only exception would be if a header file is guaranteed to be included from one and only one module. Many project managers would then require that such variable be placed at the beginning of the module, not inside any header file. Some large projects, such as the video game emulator "Mame" even require that such variables appears only above the first function using them.