我是否需要extern "C" {}
块来在C ++程序中包含标准C头。只考虑在C ++中没有对应部分的标准C头。
例如:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
答案 0 :(得分:14)
系统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
答案 1 :(得分:8)
标准未指定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>
等,它们由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)中定义为宏的是在命名空间范围(3.3.5)内 namespace std。
因此,在C ++中使用(例如)printf
的标准的,不推荐的,规范的方法是#include <cstdio>
,然后调用std::printf
。
答案 2 :(得分:2)
是的,你这样做。但是,许多系统(尤其是Linux)已经像你一样添加extern "C"
包围。请参阅(在Linux上)文件/usr/include/unistd.h
/usr/include/features.h
和__BEGIN_DECLS
中定义的宏/usr/include/sys/cdefs.h
,并在许多Linux系统包含文件中使用。
所以在Linux上,你通常可以避免使用extern "C"
,但它不会造成伤害(而且,恕我直言,在这种情况下提高可读性)。
答案 3 :(得分:1)
不,您应该使用C ++包装器标头(例如<cstdio>
)。那些照顾你的一切。
如果它是没有这些标题的标题,那么是的,您需要将它们包装在extern "C" {}
中。
ETA:值得注意的是,许多实现都会在.h文件中包含如下所示的包装器,这样您就可以自行完成。
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
答案 4 :(得分:-1)
是一个好主意,让编译器知道,以便在编译为C ++时可以期待C代码。您可能还会发现头文件本身包含extern "C" {
作为警卫。
例如,我系统上的curses.h
包含:
#ifdef __cplusplus
extern "C" {
...
答案 5 :(得分:-1)
我只是仔细检查了stdlib.h以获取GNU编译器,并且声明不使用extern“C”作为声明。
编辑:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
那么包含旧标题会在std上声明_GLIBCPP_USE_NAMESPACES定义了吗?