我是否需要一个extern "C" {}
块来在C++程序中包含标准C头文件。只考虑在C++中没有对应的标准C头文件。我是否需要一个外部“C”块来包含标准C头文件?
例如:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
我是否需要一个extern "C" {}
块来在C++程序中包含标准C头文件。只考虑在C++中没有对应的标准C头文件。我是否需要一个外部“C”块来包含标准C头文件?
例如:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
C++中的<fcntl.h>
和<unistd.h>
的行为未由标准规定(因为它们也不是C89标准的一部分)。也就是说,我从来没有见过他们(a)存在的平台和(b)实际需要被包裹在extern "C"
区块中的平台。
<stdio.h>
,<math.h>
的行为,其他标准C标头由C++ 03标准的D.5节指定。它们不需要extern "C"
包装程序块,它们将它们的符号转储到全局名称空间中。但是,附录D中的所有内容都是“不推荐使用”的。
这些头的规范C++形式是<cstdio>
,<cmath>
等,并且它们由部分17.4.1.2指定(3)C++标准,它说的:
<cassert> <ciso646> <csetjmp> <cstdio> <ctime> <cctype> <climits>
<csignal> <cstdlib> <cwchar> <cerrno> <clocale> <cstdarg> <cstring>
<cwctype>
除在第18至27条中注明,每个标题012xxcname的内容应与ISO/IEC 9899:1990编程语言C(第7章)或 中规定的 对应的标题name.h相同,即ISO/IEC:1990编程语言-C修正1:C完整性,(条款 7),如ap似乎通过包含。然而,在C++标准库 中,声明和定义(除了在C中定义为宏的名称 除外)位于名称空间标准的名称空间范围(3.3.5)内。
所以标准的,非弃用,典型的方式使用(例如)在printf
C++是#include <cstdio>
,然后调用std::printf
。
不,你应该使用C++封装报头(例如像<cstdio>
)。那些照顾你的一切。
如果这是一个头没有这些,那么是的,你会想要把它们包装在extern "C" {}
。
ETA:值得注意的是,许多实现将在下面的.h文件中包含包装器,这样你就可以不用自己做。
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
值得注意的是'
这是一个好主意,让编译器知道,以便它可以作为C++编译时预计的C代码。你也可能会发现头文件本身包含extern "C" {
作为守卫。
例如,curses.h
我的系统上载:
#ifdef __cplusplus
extern "C" {
...
*“让编译器知道,以便在编译为C++时能够期待C代码”* - 这不是什么'extern“ C“'做。它不会改变代码的解释。它甚至不适用于代码。它是一种语言链接指令,它指示编译器生成符合链接器对C语言要求的符号。它使C++代码可以从C中调用,但不会更改代码生成。 – IInspectable
@IInspectable不是_“指示编译器生成与链接器期望的符号兼容的符号”_暗示它适用于代码,或者至少是代码的调用约定?它肯定会让编译器(以及连接器)知道一些东西。 – Tanz87
@ Tanz87:它不会改变代码的生成。生成的目标代码与“extern”C“'是否相同。该指令仅适用于符号命名。它对调用约定没有影响。 – IInspectable
是的,你做的。然而,许多系统(特别是Linux)已经像你一样增加了一个extern "C"
包围。请参阅(在Linux上)文件/usr/include/unistd.h
/usr/include/features.h
和在/usr/include/sys/cdefs.h
中定义的宏__BEGIN_DECLS
,并在许多Linux系统包含文件中使用。
所以在Linux上,你通常可以避免你的extern "C"
,但它不会损害(并且,恕我直言,在这种情况下提高可读性)。
系统C头通常包含一个extern "C"
块,由#ifdef __cplusplus
保护。这样,当编译为C++时,函数会自动声明为extern "C"
,并且您不需要手动执行该操作。
例如我的系统unistd.h
上fcntl.h
开始与__BEGIN_DECLS
与__END_DECLS
结束,这是在sys/cdefs.h
定义的宏:
/* C++ needs to know that types and declarations are C, not C++. */
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
在我看来它的出口头文件的责任,用外部的“C “适当。
我刚刚检查了GNU编译器的stdlib.h,声明不使用extern“C”作为声明。
编辑:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
所以包括旧标题将放在STD提供_GLIBCPP_USE_NAMESPACES声明定义?
刚刚发现这个问题与您的问题类似:[为什么我们需要在C++中使用extern“C”{#include}?](http://stackoverflow.com/questions/67894/why-do-we-need -extern -c-include-foo-h-in-c) –
AusCBloke