我是否需要一个extern "C" {}
块来在 C++ 程序中包含标准 C 头文件。只考虑在 C++ 中没有对应的标准 C 头文件。
例如:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
系统 C 标头通常已经包含一个extern "C"
块,由#ifdef __cplusplus
. 这样,函数extern "C"
在编译为 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
<fcntl.h>
标准未指定 C++ 中的and的行为<unistd.h>
(因为它们也不是 C89 标准的一部分)。也就是说,我从未见过他们(a)存在并且(b)实际上需要包装在一个extern "C"
块中的平台。
<stdio.h>
、和其他标准 C 头文件的行为<math.h>
由 C++03 标准的 D.5 节指定。它们不需要extern "C"
包装块,它们将符号转储到全局命名空间中。但是,附件 D 中的所有内容均已“弃用”。
这些标头的规范 C++ 形式是<cstdio>
、<cmath>
等,它们由 C++ 标准的第 17.4.1.2 (3) 节指定,其中说:
<cassert> <ciso646> <csetjmp> <cstdio> <ctime> <cctype> <climits>
<csignal> <cstdlib> <cwchar> <cerrno> <clocale> <cstdarg> <cstring>
<cwctype>
除了第 18 到 27 节中的说明外,每个头文件 cname 的内容应与相应头文件 name.h 的内容相同,如 ISO/IEC 9899:1990 编程语言 C(第 7 条)或 ISO/IEC 中规定的:1990 编程语言—C 修正案 1:C 完整性,(第 7 条),视情况而定,如同包含在内。然而,在 C++ 标准库中,声明和定义(在 C 中定义为宏的名称除外)在命名空间 std 的命名空间范围 (3.3.5) 内。
printf
因此,在 C++ 中使用(例如)的标准、非弃用、规范方式是 to#include <cstdio>
然后调用std::printf
.
是的你是。但是,许多系统(尤其是 Linux)已经extern "C"
像您一样添加了括号。请参阅(在 Linux 上)文件和在许多 Linux 系统包含文件中定义和使用/usr/include/unistd.h
/usr/include/features.h
的宏 。__BEGIN_DECLS
/usr/include/sys/cdefs.h
所以在 Linux 上,你通常可以避免你的extern "C"
,但它不会有害(并且,恕我直言,在这种情况下提高可读性)。
不,您应该使用 C++ 包装头文件(例如 like <cstdio>
)。那些会为你处理所有这些。
如果它是一个没有这些的标题,那么是的,您需要将它们包装在extern "C" {}
.
ETA:值得注意的是,许多实现将在 .h 文件中包含包装器,如下所示,这样您就可以不用自己动手了。
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
最好让编译器知道,以便在编译为 C++ 时可以预期 C 代码。您可能还会发现头文件本身包含extern "C" {
作为警卫。
例如,curses.h
在我的系统上包含:
#ifdef __cplusplus
extern "C" {
...
我只是仔细检查了 GNU 编译器的 stdlib.h 并且声明不使用 extern "C" 作为声明。
编辑:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
因此,如果 _GLIBCPP_USE_NAMESPACES 已定义,包括旧标题将在 std 上放置声明?