如何正确使用C中的extern关键字

时间:2022-09-07 21:08:47

My question is about when a function should be referenced with the extern keyword in C.

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

I am failing to see when this should be used in practice. As I am writing a program all of the functions that I use are made available through the header files I have included. So why would it be useful to extern to get access to something that was not exposed in the header file?

我不知道什么时候应该在实践中使用它。当我在编写一个程序时,我使用的所有函数都可以通过我包含的头文件获得。那么,为什么对extern来说,获取未在头文件中公开的内容是有用的呢?

I could be thinking about how extern works incorrectly, and if so please correct me.

我可能在想外面是怎么工作的,如果是的话,请纠正我。

Edit: Should you extern something when it is the default declaration without the keyword in a header file?

编辑:当它是头文件中没有关键字的默认声明时,你应该对它进行外部处理吗?

10 个解决方案

#1


249  

"extern" changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.

“外来的”变化的联系。使用关键字,假设函数/变量在其他地方可用,而解析则被延迟到链接器。

There's a difference between "extern" on functions and on variables: on variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else. For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword "static" to indicate that a function is not bound using extern linkage) you don't need to use it explicitly.

函数和变量的“extern”之间存在差异:在变量上,它不实例化变量本身,也就是说不分配任何内存。这需要在别的地方做。因此,如果要从其他地方导入变量,这一点很重要。对于函数,这只告诉编译器链接是extern。由于这是默认值(您使用关键字“static”来表示函数没有使用extern链接进行绑定),因此不需要显式地使用它。

#2


167  

extern tells the compiler that this data is defined somewhere and will be connected with the linker.

extern告诉编译器该数据在某处被定义并将与链接器连接。

With the help of the responses here and talking to a few friends here is the practical example of a use of extern.

在这里的回答和与一些朋友的交谈中,这是一个使用外部的实际例子。

Example 1 - to show a pitfall:

示例1 -显示陷阱:

File stdio.h:

int errno;
/* other stuff...*/

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

If myCFile1.o and myCFile2.o are linked, each of the c files have separate copies of errno. This is a problem as the same errno is supposed to be available in all linked files.

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

Example 2 - The fix.

例2 -修复。

File stdio.h:

extern int errno;
/* other stuff...*/

File stdio.c

int errno;

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

Now if both myCFile1.o and MyCFile2.o are linked by the linker they will both point to the same errno. Thus, solving the implementation with extern.

现在如果myCFile1。o和MyCFile2。o由链接器连接,它们都指向同一个错误。因此,在外部解决实现。

#3


25  

It has already been stated that the extern keyword is redundant for functions.

已经说明了extern关键字对于函数而言是多余的。

As for variables shared across compilation units, you should declare them in a header file with the extern keyword, then define them in a single source file, without the extern keyword. The single source file should be the one sharing the header file's name, for best practice.

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

#4


14  

In C, 'extern' is implied for function prototypes, as a prototype declares a function which is defined somewhere else. In other words, a function prototype has external linkage by default; using 'extern' is fine, but is redundant.

在C语言中,“extern”表示函数原型,因为原型声明了在其他地方定义的函数。换句话说,一个函数原型默认有外部链接;使用“extern”是可以的,但它是多余的。

(If static linkage is required, the function must be declared as 'static' both in its prototype and function header, and these should normally both be in the same .c file).

(如果需要静态链接,那么函数在原型和函数头中都必须声明为“静态”,而这些通常都应该在相同的.c文件中)。

#5


9  

Many years later, I discover this question. After reading every answers and comments, I though I could clarify a few details ... This could be useful for people who get here thru goggle search.

许多年后,我发现了这个问题。读完所有的答案和评论,我想我可以澄清一些细节……这可能对通过goggle search来到这里的人有用。

The question is specifically about using "extern" functions, so I will ignore the use of "extern" with global variables.

这个问题是关于使用“extern”函数的,因此我将忽略使用“extern”时全局变量的使用。

Let's define 3 function prototypes

让我们定义三个函数原型。

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

The header file can be used by the main source code as follow

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

//--------------------------------------
//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;

In order to compile and link, we must define "function_2" in the same source code file where we call that function. The two other functions could be defined in a different source code ".C" or they may be located in any binary file (.OBJ, *.LIB, *.DLL), for which we may not have the source code.

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

Lets include again the header "my_project.H" in a different "*.C" file to understand better the difference. In the same project, we add the following file //--------------------------------------

让我们再次包含标题“my_project”。H" in a different "*。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;

Important features to notice: 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 use 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.

作为C库一部分的函数只能在一个模块中替换,只需在该模块中重新定义一个“静态”原型。例如,替换任何对“malloc”和“free”的调用,以添加内存泄漏检测特性。

The specifier "extern" is not really needed for functions. When "static" is not found, a function is always assumed to be "extern'.

函数实际上并不需要特殊的“extern”。当没有找到“static”时,函数总是被假定为“extern”。

However, "extern" is not the default for variables. Normally, any header file that define variables to be visible across many modules need to use "extern". The only exception would be if a header file is guaranteed to be included from one and only one module.

但是,“extern”不是变量的默认值。通常,任何定义跨许多模块可见变量的头文件都需要使用“extern”。唯一的例外是如果一个头文件被保证包含在一个模块中,而且只有一个模块。

Many project manager 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 variable appear only above the first function using them.

许多项目经理会要求将这个变量放在模块的开始部分,而不是任何头文件中。一些大型项目,比如视频游戏仿真器“Mame”甚至要求这些变量只出现在第一个函数的上面。

#6


8  

A very good article that I came about the extern keyword, along with the examples: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

我写了一篇关于extern关键字的很好的文章,文中有如下示例:http://www.geeksforgeeks.org/understand - outside -keyword-in-c/

Though I do not agree that using extern in function declarations is redundant. This is supposed to be a compiler setting. So I recommend using the extern in the function declarations when it is needed.

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

#7


5  

If each file in your program is first compiled to an object file, then the object files are linked together, you need extern. It tells the compiler "This function exists, but the code for it is somewhere else. Don't panic."

如果程序中的每个文件首先被编译成一个对象文件,那么对象文件将被链接在一起,您需要外部。它告诉编译器“这个函数存在,但是它的代码在其他地方。”不要惊慌。”

#8


4  

All declarations of functions and variables in header files should be extern.

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

Exceptions to this rule are inline functions defined in the header and variables which - although defined in the header - will have to be local to the translation unit (the source file the header gets included into): these should be static.

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

In source files, extern shouldn't be used for functions and variables defined in the file. Just prefix local definitions with static and do nothing for shared definitions - they'll be external symbols by default.

在源文件中,extern不应用于文件中定义的函数和变量。只要在本地定义中使用静态前缀,对共享定义不做任何操作,默认情况下它们将是外部符号。

The only reason to use extern at all in a source file is to declare functions and variables which are defined in other source files and for which no header file is provided.

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


Declaring function prototypes extern is actually unnecessary. Some people dislike it because it will just waste space and function declarations already have a tendency to overflow line limits. Others like it because this way, functions and variables can be treated the same way.

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

#9


2  

When you have that function defined on a different dll or lib, so that the compiler defers to the linker to find it. Typical case is when you are calling functions from the OS API.

当您在一个不同的dll或lib上定义了这个函数时,编译器就会转向链接器来查找它。典型的情况是当您从OS API调用函数时。

#10


2  

Functions actually defined in other source files should only be declared in headers. In this case, you should use extern when declaring the prototype in a header.

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

Most of the time, your functions will be one of the following (more like a best practice):

大多数时候,您的功能将是以下之一(更像是最佳实践):

  • static (normal functions that aren't visible outside that .c file)
  • 静态(在该.c文件之外不可见的正常函数)
  • static inline (inlines from .c or .h files)
  • 静态内联(来自.c或.h文件的内联)
  • extern (declaration in headers of the next kind (see below))
  • extern(下一类header中的声明(见下文))
  • [no keyword whatsoever] (normal functions meant to be accessed using extern declarations)
  • [没有任何关键字](使用extern声明时意味着访问的正常函数)

#1


249  

"extern" changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.

“外来的”变化的联系。使用关键字,假设函数/变量在其他地方可用,而解析则被延迟到链接器。

There's a difference between "extern" on functions and on variables: on variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else. For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword "static" to indicate that a function is not bound using extern linkage) you don't need to use it explicitly.

函数和变量的“extern”之间存在差异:在变量上,它不实例化变量本身,也就是说不分配任何内存。这需要在别的地方做。因此,如果要从其他地方导入变量,这一点很重要。对于函数,这只告诉编译器链接是extern。由于这是默认值(您使用关键字“static”来表示函数没有使用extern链接进行绑定),因此不需要显式地使用它。

#2


167  

extern tells the compiler that this data is defined somewhere and will be connected with the linker.

extern告诉编译器该数据在某处被定义并将与链接器连接。

With the help of the responses here and talking to a few friends here is the practical example of a use of extern.

在这里的回答和与一些朋友的交谈中,这是一个使用外部的实际例子。

Example 1 - to show a pitfall:

示例1 -显示陷阱:

File stdio.h:

int errno;
/* other stuff...*/

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

If myCFile1.o and myCFile2.o are linked, each of the c files have separate copies of errno. This is a problem as the same errno is supposed to be available in all linked files.

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

Example 2 - The fix.

例2 -修复。

File stdio.h:

extern int errno;
/* other stuff...*/

File stdio.c

int errno;

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

Now if both myCFile1.o and MyCFile2.o are linked by the linker they will both point to the same errno. Thus, solving the implementation with extern.

现在如果myCFile1。o和MyCFile2。o由链接器连接,它们都指向同一个错误。因此,在外部解决实现。

#3


25  

It has already been stated that the extern keyword is redundant for functions.

已经说明了extern关键字对于函数而言是多余的。

As for variables shared across compilation units, you should declare them in a header file with the extern keyword, then define them in a single source file, without the extern keyword. The single source file should be the one sharing the header file's name, for best practice.

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

#4


14  

In C, 'extern' is implied for function prototypes, as a prototype declares a function which is defined somewhere else. In other words, a function prototype has external linkage by default; using 'extern' is fine, but is redundant.

在C语言中,“extern”表示函数原型,因为原型声明了在其他地方定义的函数。换句话说,一个函数原型默认有外部链接;使用“extern”是可以的,但它是多余的。

(If static linkage is required, the function must be declared as 'static' both in its prototype and function header, and these should normally both be in the same .c file).

(如果需要静态链接,那么函数在原型和函数头中都必须声明为“静态”,而这些通常都应该在相同的.c文件中)。

#5


9  

Many years later, I discover this question. After reading every answers and comments, I though I could clarify a few details ... This could be useful for people who get here thru goggle search.

许多年后,我发现了这个问题。读完所有的答案和评论,我想我可以澄清一些细节……这可能对通过goggle search来到这里的人有用。

The question is specifically about using "extern" functions, so I will ignore the use of "extern" with global variables.

这个问题是关于使用“extern”函数的,因此我将忽略使用“extern”时全局变量的使用。

Let's define 3 function prototypes

让我们定义三个函数原型。

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

The header file can be used by the main source code as follow

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

//--------------------------------------
//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;

In order to compile and link, we must define "function_2" in the same source code file where we call that function. The two other functions could be defined in a different source code ".C" or they may be located in any binary file (.OBJ, *.LIB, *.DLL), for which we may not have the source code.

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

Lets include again the header "my_project.H" in a different "*.C" file to understand better the difference. In the same project, we add the following file //--------------------------------------

让我们再次包含标题“my_project”。H" in a different "*。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;

Important features to notice: 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 use 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.

作为C库一部分的函数只能在一个模块中替换,只需在该模块中重新定义一个“静态”原型。例如,替换任何对“malloc”和“free”的调用,以添加内存泄漏检测特性。

The specifier "extern" is not really needed for functions. When "static" is not found, a function is always assumed to be "extern'.

函数实际上并不需要特殊的“extern”。当没有找到“static”时,函数总是被假定为“extern”。

However, "extern" is not the default for variables. Normally, any header file that define variables to be visible across many modules need to use "extern". The only exception would be if a header file is guaranteed to be included from one and only one module.

但是,“extern”不是变量的默认值。通常,任何定义跨许多模块可见变量的头文件都需要使用“extern”。唯一的例外是如果一个头文件被保证包含在一个模块中,而且只有一个模块。

Many project manager 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 variable appear only above the first function using them.

许多项目经理会要求将这个变量放在模块的开始部分,而不是任何头文件中。一些大型项目,比如视频游戏仿真器“Mame”甚至要求这些变量只出现在第一个函数的上面。

#6


8  

A very good article that I came about the extern keyword, along with the examples: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

我写了一篇关于extern关键字的很好的文章,文中有如下示例:http://www.geeksforgeeks.org/understand - outside -keyword-in-c/

Though I do not agree that using extern in function declarations is redundant. This is supposed to be a compiler setting. So I recommend using the extern in the function declarations when it is needed.

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

#7


5  

If each file in your program is first compiled to an object file, then the object files are linked together, you need extern. It tells the compiler "This function exists, but the code for it is somewhere else. Don't panic."

如果程序中的每个文件首先被编译成一个对象文件,那么对象文件将被链接在一起,您需要外部。它告诉编译器“这个函数存在,但是它的代码在其他地方。”不要惊慌。”

#8


4  

All declarations of functions and variables in header files should be extern.

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

Exceptions to this rule are inline functions defined in the header and variables which - although defined in the header - will have to be local to the translation unit (the source file the header gets included into): these should be static.

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

In source files, extern shouldn't be used for functions and variables defined in the file. Just prefix local definitions with static and do nothing for shared definitions - they'll be external symbols by default.

在源文件中,extern不应用于文件中定义的函数和变量。只要在本地定义中使用静态前缀,对共享定义不做任何操作,默认情况下它们将是外部符号。

The only reason to use extern at all in a source file is to declare functions and variables which are defined in other source files and for which no header file is provided.

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


Declaring function prototypes extern is actually unnecessary. Some people dislike it because it will just waste space and function declarations already have a tendency to overflow line limits. Others like it because this way, functions and variables can be treated the same way.

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

#9


2  

When you have that function defined on a different dll or lib, so that the compiler defers to the linker to find it. Typical case is when you are calling functions from the OS API.

当您在一个不同的dll或lib上定义了这个函数时,编译器就会转向链接器来查找它。典型的情况是当您从OS API调用函数时。

#10


2  

Functions actually defined in other source files should only be declared in headers. In this case, you should use extern when declaring the prototype in a header.

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

Most of the time, your functions will be one of the following (more like a best practice):

大多数时候,您的功能将是以下之一(更像是最佳实践):

  • static (normal functions that aren't visible outside that .c file)
  • 静态(在该.c文件之外不可见的正常函数)
  • static inline (inlines from .c or .h files)
  • 静态内联(来自.c或.h文件的内联)
  • extern (declaration in headers of the next kind (see below))
  • extern(下一类header中的声明(见下文))
  • [no keyword whatsoever] (normal functions meant to be accessed using extern declarations)
  • [没有任何关键字](使用extern声明时意味着访问的正常函数)