Нужен ли мне блок extern " C " для включения стандартных заголовков C?
мне нужно extern "C" {}
блок для включения стандартных заголовков C в программу на C++. Рассматривать только стандартные заголовки C, которые не имеют аналогов в C++.
например:
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
6 ответов
поведение <fcntl.h>
и <unistd.h>
в C++ не указывается стандартом (поскольку они также не являются частью стандарта C89). Тем не менее, я никогда не видел платформу, где они (а) существуют и (Б) на самом деле должны быть завернуты в extern "C"
заблокировать.
поведение <stdio.h>
, <math.h>
, а другие стандартные заголовки C указаны в разделе D. 5 стандарта C++03. Они не требуют extern "C"
блок оболочки, и они сбрасывают свои символы в глобальный пространство имен. Однако все в приложении D является "устаревшим".
канонической формой c++ этих заголовков является <cstdio>
, <cmath>
, etc., и они указаны в разделе 17.4.1.2 (3) стандарта C++, в котором говорится:
<cassert> <ciso646> <csetjmp> <cstdio> <ctime> <cctype> <climits>
<csignal> <cstdlib> <cwchar> <cerrno> <clocale> <cstdarg> <cstring>
<cwctype>
за исключением случаев, указанных в пунктах 18-27, содержимое каждого заголовка cname должен совпадать с именем соответствующего заголовка.h, как указанных в стандарте ISO / IEC 9899: 1990 языки программирования C (пункт 7), или ISO / IEC: 1990 Языки программирования-C поправка 1: C целостность, (пункт 7), по мере необходимости, как бы путем включения. В стандартной библиотеке C++ , однако объявления и определения (за исключением имен, которые определенные как макросы в C) находятся в области пространства имен (3.3.5) пространства имен std.
таким образом, стандартный, не устаревший, канонический способ использования (например) printf
в C++ есть #include <cstdio>
и затем вызвать std::printf
.
заголовки system C обычно уже включают a 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
Да, ты знаешь. Однако многие системы (особенно Linux) уже добавляют extern "C"
брекетинг, как вы делаете. См. (в Linux) файлы /usr/include/unistd.h
/usr/include/features.h
и макрос __BEGIN_DECLS
определена в /usr/include/sys/cdefs.h
и используется во многих системах Linux включают файлы.
Итак, в Linux вы обычно можете избежать своего extern "C"
но это не вредит (и, ИМХО, улучшает читаемость в этом случае).
нет, вы должны использовать заголовки оболочки C++ (например, как <cstdio>
). Они обо всем позаботятся.
Если это заголовок, который не имеет их, то да, вы захотите обернуть их в extern "C" {}
.
ЕТА: стоит отметить, что многие реализации будут включать обертку внутри .H-файл, как показано ниже, так что вы можете уйти с делать это самостоятельно.
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
Это is хорошая идея сообщить компилятору, чтобы он мог ожидать код C при компиляции как c++. Вы также можете обнаружить, что сами файлы заголовков содержат extern "C" {
в качестве охранников.
например, curses.h
в моей системе содержит:
#ifdef __cplusplus
extern "C" {
...
Я просто дважды проверил stdlib.h для компилятора GNU и деклараций extern "C" в качестве деклараций не используется.
изменить:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
Так как старая заголовки будут размещать объявления о предоставляемых _GLIBCPP_USE_NAMESPACES СТД определяется?