在C++程序中,我需要使用extern "C" {}
块来包含标准C头文件吗?只考虑在C++中没有对应项的标准C头文件。
例如:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
#ifdef __cplusplus
守卫的extern "C"
块。这样,当编译为C++时,函数会自动声明为extern "C"
,因此您无需手动执行此操作。
例如,在我的系统上,unistd.h
和 fcntl.h
以sys/cdefs.h
中定义的宏__BEGIN_DECLS
和__END_DECLS
开始和结束:/* 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>
和<unistd.h>
在C++中的行为未被标准指定(因为它们也不是C89标准的一部分)。尽管如此,我从未见过一个需要将它们包装在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条款中所述的内容外,每个头文件的名称应该和对应的C语言标准库头文件名字相同,根据ISO/IEC 9899:1990 Programming Languages C(第7条)或 ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity (第7条)进行指定。在C++标准库中,除了被定义为宏的名称外,声明和定义都处于命名空间std的范围内(3.3.5)。因此,在C++中使用(例如)printf的标准、非废弃、规范的方法是# include ,然后调用std::printf。extern "C"
括号。在Linux上,请参见文件/usr/include/unistd.h
、/usr/include/features.h
以及在许多Linux系统包含文件中使用的宏__BEGIN_DECLS
在/usr/include/sys/cdefs.h
中定义。
因此,在Linux上,你通常可以避免使用extern "C"
,但这并不会有害(并且,在这种情况下,我认为它可以提高可读性)。
不,你应该使用C++的包装头文件(例如像<cstdio>
这样)。它们会为你处理所有的事情。
如果是一个没有这些的头文件,那么是的,你需要用extern "C" {}
来包装它们。
预计时间:值得注意的是,许多实现会在.h文件中包含包装器,就像下面这样,这样你就可以省去自己做的麻烦。
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
<cstdio>
等头文件在技术上将它们的定义放在了std
命名空间中。(许多实现也将它们放在顶层命名空间中,但这不是标准规定的。) - Nemo我刚刚仔细检查了 GNU 编译器的 stdlib.h,发现它的声明没有使用 extern "C"。
编辑:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
因此,如果包括旧标头,则会在定义了std提供的_GLIBCPP_USE_NAMESPACES时放置声明吗?
在编译为 C++ 时,让编译器知道这一点是一个好主意,这样它就可以期望编译 C 代码。您可能还会发现头文件本身包含 extern "C" {
作为保护。
例如,我的系统上的 curses.h
包含:
#ifdef __cplusplus
extern "C" {
...
extern "C"
的作用。它不会改变代码的解释,甚至不适用于代码。它是一种语言链接指令,指示编译器生成与链接器期望的C兼容的符号。它使得C++代码可从C中调用,但不会改变代码生成。 - IInspectable