是否还需要在源文件中添加“extern C”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2168241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it required to add 'extern C' in source file also?
提问by Jay
I found some code recently where extern "C" was added in source file also for functions. They were also added in the header files where they were declared.
我最近发现了一些代码,其中在源文件中也为函数添加了 extern "C"。它们也被添加到声明它们的头文件中。
I was under the assumption that adding 'extern "C" in header files was sufficient.
我假设在头文件中添加 'extern "C" 就足够了。
Where should extern "C" blocks be added?
应该在哪里添加外部“C”块?
UPDATE: Suppose I am compiling my C code using a CPP compiler and have added extern "C" guards for all the functions in header files (i.e. all my functions have their prototypes in headers), but in source files I have not added the same. Will this cause a problem?
更新:假设我正在使用 CPP 编译器编译我的 C 代码,并为头文件中的所有函数添加了 extern "C" 保护(即我的所有函数在头文件中都有它们的原型),但在源文件中我没有添加相同的. 这会导致问题吗?
回答by Adam Bowen
Since you mean
既然你的意思
extern "C" { ... }
style guards, these declare some functions to be of "C" linkage, rather than "C++" linkage (which typically has a bunch of extra name decoration to support things like overloaded functions).
样式守卫,这些声明一些函数是“C”链接,而不是“C++”链接(通常有一堆额外的名称修饰来支持重载函数之类的东西)。
The purpose, of course, is to allow C++ code to interface with C code, which is usually in a library. If the library's headers weren't written with C++ in mind, then they won't include the extern "C"
guards for C++.
当然,目的是允许 C++ 代码与通常位于库中的 C 代码交互。如果库的头文件不是用 C++ 编写的,那么它们就不会包含extern "C"
C++的守卫。
A C header written with C++ in mind will include something along the lines of
考虑到 C++ 编写的 AC 头文件将包含以下内容
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif
to make sure C++ programs see the correct linkage. However, not all libraries were written with C++ in mind, so sometimes you have to do
确保 C++ 程序看到正确的链接。然而,并不是所有的库都是用 C++ 编写的,所以有时你必须这样做
extern "C" {
#include "myclibrary.h"
}
to get the linkage correct. If the header file is provided by someone else then it's not good practice to change it (because then you can't update it easily), so it's better to wrap the header file with your own guard (possibly in your own header file).
以获得正确的链接。如果头文件是由其他人提供的,那么更改它不是一个好习惯(因为这样你就不能轻易更新它),所以最好用你自己的保护(可能在你自己的头文件中)包装头文件。
extern "C"
isn't (AFAIK) ANSI C, so can't be included in normal C code without the preprocessor guards.
extern "C"
不是(AFAIK)ANSI C,因此不能在没有预处理器保护的情况下包含在普通 C 代码中。
In response to your edit:
回应您的编辑:
If you are using a C++ compiler, and you declare a function as extern "C" in the header file, you do not need to also declare that function as extern "C" in the implementation file. From section 7.5 of the C++ standard (emphasis mine):
如果您使用的是 C++ 编译器,并且在头文件中将函数声明为 extern "C",则不需要在实现文件中将该函数也声明为 extern "C"。来自 C++ 标准的第 7.5 节(强调我的):
If two declarations of the same function or object specify different linkage-specifications (that is, the linkage-specifications of these declarations specify different string-literals), the program is ill-formed if the declarations appear in the same translation unit, and the one definition rule applies if the declarations appear in different translation units. Except for functions with C++ linkage, a function declaration without a linkage specification shall not precede the first linkage specification for that function. A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.
如果同一个函数或对象的两个声明指定了不同的链接规范(即这些声明的链接规范指定了不同的字符串文字),如果声明出现在同一个翻译单元中,程序就是格式错误的,并且如果声明出现在不同的翻译单元中,则适用一个定义规则。除具有 C++ 链接的函数外,没有链接规范的函数声明不应在该函数的第一个链接规范之前。在看到显式链接规范后,可以在没有链接规范的情况下声明函数;先前声明中明确指定的链接不受此类函数声明的影响。
I'm not convinced it's good practice though, since there's the potential for the linkage specifications to diverge by accident (if, for example, the header file containing the linkage specification isn't included in the implementing file). I think it's better to be explicit in the implementation file.
不过,我不相信这是一种好的做法,因为链接规范有可能会意外发生分歧(例如,如果包含链接规范的头文件未包含在实现文件中)。我认为最好在实现文件中明确。
回答by Peter Alexander
They only need to go in anything that is included by other source files.
他们只需要进入其他源文件包含的任何内容。
With some idiomsyou'll find people including source files.
使用一些习语,您会发现包含源文件的人。
回答by Georg Sch?lly
They should be added to all files, that get included in other files.
它们应该添加到所有文件中,这些文件包含在其他文件中。
Normally, one doesn't include source files.
通常,一个不包括源文件。
回答by Remy
You mean the 'extern c' preprocessors? They have to be on the function definition as well as that affects how the function call is stored in the compiled binary. Its only really needed if you are linking compiled c++ together with c which is compiled as C (as opposed to c in a .cpp file).
你的意思是'extern c'预处理器?它们必须在函数定义上,并且会影响函数调用在编译后的二进制文件中的存储方式。只有当您将编译的 c++ 与编译为 C 的 c 链接在一起时才真正需要它(而不是 .cpp 文件中的 c)。
回答by Jonathan Leffler
Apologia
道歉
The question has changed to be much clearer what it was asking about. This answer addressed the original question, when it was at least debatable whether it was discussing guards against multiple inclusion in header files - which is what my answer addresses. Clearly, if the question had been as clear then as it is now, I would not have submitted this answer.
问题已经变得更清楚了它在问什么。这个答案解决了最初的问题,当时至少有争议的是,它是否正在讨论防止头文件中的多重包含 - 这就是我的答案所解决的问题。显然,如果当时的问题和现在一样清楚,我就不会提交这个答案。
Original answer
原答案
No, it is not necessary to include the guards in the C code too.
不,也没有必要在 C 代码中包含守卫。
If the header file 'header.h' says:
如果头文件 'header.h' 说:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
...
#endif
Then it is perfectly safe for a source file 'source.c' to say:
那么源文件“source.c”说:
#include "header.h"
It is also safe for other headers to include 'header.h'.
包含“header.h”的其他头文件也是安全的。
However, people note that opening a header file and reading it takes time, which slows up a compilation, so sometimes people do things like:
但是,人们注意到打开头文件并阅读它需要时间,这会减慢编译速度,因此有时人们会这样做:
#ifndef HEADER_H_INCLUDED
#include "header.h"
#endif
This means that if some other header included in 'source.c' has already included 'header.h', then the '#include' is not re-processed. (Or, if 'header.h' has already been included directly in 'source.c', though that's a silly buglet.)
这意味着如果包含在 'source.c' 中的其他头文件已经包含了 'header.h',则不会重新处理 '#include'。(或者,如果 'header.h' 已经直接包含在 'source.c' 中,尽管这是一个愚蠢的小程序。)
So, when encountered, it is likely to be an attempt to optimize the compilation performance. It is far from clear that it buys you much; modern C preprocessors are fairly intelligent about the issue and will avoid re-including the file if they can. And there's always a risk that the test in 'source.c' has a typo (#ifndef HEARER_H_INCLUDED, perhaps) in which case the test slows the compilation because the preprocessor tests the irrelevant condition and then proceeds to include 'header.h' after all. It is 'safe'; the header is itself protected-- or should be.
所以,遇到时,很可能是为了优化编译性能。远不清楚它会为您购买多少。现代 C 预处理器对这个问题相当聪明,并且会尽可能避免重新包含文件。并且始终存在“source.c”中的测试有拼写错误(可能是#ifndef HEARER_H_INCLUDED)的风险,在这种情况下,测试会减慢编译速度,因为预处理器会测试不相关的条件,然后在之后继续包含“header.h”全部。它是“安全的”;标头本身受到保护——或者应该受到保护。
If you see the code in 'source.c' also doing '#define HEADER_H_INCLUDED', then there are problems. The #define has to be either before or after the #include, and neither is good as a general technique.
如果您看到“source.c”中的代码也在执行“#define HEADER_H_INCLUDED”,则说明存在问题。#define 必须在#include 之前或之后,两者都不是通用技术。
- If 'source.c' does '#define HEADER_H_INCLUDED' before including 'header.h', then if the guard appears in 'header.h', the contents of the header will not be included. If the guard does not appear in 'header.h', then things work OK.
- If 'source.c' does '#define HEADER_H_INCLUDED' after including 'header.h', then if the guard appears in 'header.h', we get a benign redefinition of HEADER_H_INCLUDED. If 'header.h' does not contain the guard but does include a file which includes 'header.h', you are not protected from multiple inclusion after all.
- 如果 'source.c' 在包含 'header.h' 之前做了 '#define HEADER_H_INCLUDED',那么如果在 'header.h' 中出现了守卫,则不会包含头文件的内容。如果守卫没有出现在'header.h'中,那么一切正常。
- 如果 'source.c' 在包含 'header.h' 之后执行了 '#define HEADER_H_INCLUDED',那么如果守卫出现在 'header.h' 中,我们就会得到 HEADER_H_INCLUDED 的良性重新定义。如果 'header.h' 不包含守卫,但确实包含一个包含 'header.h' 的文件,那么您毕竟不受多重包含的保护。
Note that body of the header appears after the '#define HEADER_H_INCLUDED'. This is again protection if nested includes include 'header.h'.
请注意,标题的正文出现在“#define HEADER_H_INCLUDED”之后。如果嵌套包含 include 'header.h',这又是一种保护。
回答by VoidPointer
The "C" guards have two purposes:
“C”守卫有两个目的:
- When your code is compiled, the functions will be exported in a way that will allow a non C++ compiler/linker to use them (no C++ name mangling etc.)
- When a C++ compiler uses your header files, it will know that it should bind the symbols in the C way which in turn will make sure that the resulting program will link successfully. They don't carry a meaning for a non C++ compiler but since the symbols were generated in C-style in (1) this is the desired effect.
- 编译代码时,函数将以允许非 C++ 编译器/链接器使用它们的方式导出(无 C++ 名称修改等)
- 当 C++ 编译器使用您的头文件时,它会知道它应该以 C 方式绑定符号,从而确保生成的程序将成功链接。它们对非 C++ 编译器没有意义,但由于符号是在 (1) 中以 C 样式生成的,这是预期的效果。
Since you include the header with the "C" guards also in your implementation file, the information on how the symbols should be created at compile time is available to the compiler and the compiler will create the symbols in a way that can be used by a non C++ compiler. Consequently you only need to specify extern "C"in your header file as long as the header file is also included by the implementation file.
由于您的实现文件中也包含带有“C”保护的头文件,因此编译器可以使用有关在编译时如何创建符号的信息,并且编译器将以一种可由非 C++ 编译器。因此,只要头文件也包含在实现文件中,您只需在头文件中指定extern "C"。
回答by Emil.Thomas
it is not required for extern to be used in source files, if they are used in the header file and that file is included by the rest of the source files.
如果在头文件中使用了 extern 并且该文件包含在其余的源文件中,则不需要在源文件中使用 extern。
As far as I remember the standard, all function declarations are considered as "extern" by default, so there is no need to specify it explicitly. That doesn't make this keyword useless since it can also be used with variables (and it that case - it's the only solution to solve linkage problems). But with the functions - yes, it's optional.
就我记得的标准而言,默认情况下所有函数声明都被视为“extern”,因此无需明确指定。这不会使这个关键字无用,因为它也可以与变量一起使用(在这种情况下 - 它是解决链接问题的唯一解决方案)。但是对于功能 - 是的,它是可选的。
A little more verbose answer is that it allows you to use variables compiled in another source code file, but doesn't reserve memory for the variable. So, to utilise extern, you have to have a source code file or a library unit that contains memory space for the variable on the top level (not within functions). Now, you can refer to that variable by defining an extern variable of the same name in your other source code files.
稍微详细一点的答案是它允许您使用在另一个源代码文件中编译的变量,但不为变量保留内存。因此,要使用 extern,您必须有一个源代码文件或一个库单元,其中包含顶层变量(不在函数内)的内存空间。现在,您可以通过在其他源代码文件中定义同名的外部变量来引用该变量。
In general, the use of extern definition should be avoided. They lead easily to unmanagable code and errors that hard to locate. Of course, there are examples where other solutions would be impractical, but they are rare. For example, stdin and stdout are macros that are mapped to an extern array variable of type FILE* in stdin.h; memory space for this array is in a standard C-library unit.
通常,应避免使用 extern 定义。它们很容易导致无法管理的代码和难以定位的错误。当然,也有其他解决方案不切实际的例子,但这种情况很少见。例如,stdin 和stdout 是映射到stdin.h 中FILE* 类型的extern 数组变量的宏;此数组的存储空间位于标准 C 库单元中。