В *.h
заголовочных файлах библиотеки C
следует объявить функции
extern void f();
// or only
void f();
- при использовании только в
C
- при использовании из
C++
.
В *.h
заголовочных файлах библиотеки C
следует объявить функции
extern void f();
// or only
void f();
C
C++
.Там [почти] никогда не нужно использовать ключевое слово extern
при объявлении функции, либо в C, либо в С++. В C и на С++ все функции имеют внешнюю связь по умолчанию. Странная привычка объявлять функции в заголовочных файлах с extern
, вероятно, имеет некоторые исторические корни, но уже десятилетиями она уже неактуальна.
Существует одно исключение из вышеприведенного в C, которое, вероятно, напрямую не связано с тем, о чем вы спрашиваете: на языке C (C99), если в некоторой единицы перевода функция определена как inline
, а также объявленный как extern
(используется явный extern
), тогда встроенное определение этой функции также служит внешним определением. Если в блоке трансляции нет деклараций с явным extern
, тогда встроенное определение используется только как "внутреннее" определение.
P.S. В С++ существует такая вещь, как extern "C"
, но это совершенно другое дело.
В заголовочных файлах библиотеки C следует объявить функции:
extern void f(); // or only void f();
В программе на С++ функции объявляются как функции, не возвращающие значения и не принимающие аргументов.
В программе C функции объявляются как функции, не возвращающие значения и принимающие неопределенный, но не переменный список аргументов.
Чтобы получить значение "без аргументов" в C, используйте один из:
extern void f(void);
void f(void);
То же самое обозначение также означает то же самое в С++, хотя для чистого кода на С++ использование void
в списке аргументов не является идиоматическим (не делайте этого в чистом С++-коде).
Трудно, но нормальное правило должно было бы объявить функции С++-кодом как extern "C"
. Чтобы использовать тот же исходный код для обоих, вам необходимо проверить макрос __cplusplus
. Обычно вы делаете что-то вроде:
#ifdef __cplusplus
#define EXTERN_C extern "C"
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C /* Nothing */
#define EXTERN_C_BEGIN /* Nothing */
#define EXTERN_C_END /* Nothing */
#endif
EXTERN_C void f(void);
EXTERN_C_BEGIN
void f(void);
int g(int);
EXTERN_C_END
Параметры и варианты являются многообразными, но заголовок может использоваться как C, так и С++.
Макросы обычно определяются в одном универсальном заголовке, который используется повсюду, а затем конкретный заголовок гарантирует включение заголовка общего назначения, а затем использует соответствующую форму макроса.
Формально, нет необходимости в обозначении extern
перед объявлением функции. Однако я использую его в заголовках, чтобы подчеркнуть, что это объявление функции, определяемой извне, и для симметрии с теми (редко) случаями, когда есть глобальная переменная, объявленная в заголовке.
Люди могут и не соглашаются с этим; Я использую локальные правила, но когда я являюсь создателем правил, extern
включен в заголовок.
Для общего использования объявляйте как
#ifdef __cplusplus
extern "C" {
#endif
void f(void);
#ifdef __cplusplus
}
#endif
В противном случае extern
устарел.
Последнее прекрасно, поскольку это только определение функции, которое сообщает тем, кто включает этот заголовок: "Там есть функция с этим прототипом где-то здесь"
В этом контексте функции явно отличаются от переменных, но это другое дело. Однако убедитесь, что вы не включаете тело функции, если вы не объявляете его "inline" или частью определения класса (С++) или как "функция шаблона" (также С++).
Задание extern в прототипе функции не влияет, поскольку по умолчанию предполагается. Всякий раз, когда компилятор видит прототип, он предполагает, что функция определена где-то в другом (в текущей или другой единицы перевода). Это выполняется для обоих языков.
В следующем потоке есть некоторые полезные комментарии в целом об extern.