Подтвердить что ты не робот

Внешние функции в C vs С++

В *.h заголовочных файлах библиотеки C следует объявить функции

extern void f();

// or only 

void f();
  • при использовании только в C
  • при использовании из C++.
4b9b3361

Ответ 1

Там [почти] никогда не нужно использовать ключевое слово extern при объявлении функции, либо в C, либо в С++. В C и на С++ все функции имеют внешнюю связь по умолчанию. Странная привычка объявлять функции в заголовочных файлах с extern, вероятно, имеет некоторые исторические корни, но уже десятилетиями она уже неактуальна.

Существует одно исключение из вышеприведенного в C, которое, вероятно, напрямую не связано с тем, о чем вы спрашиваете: на языке C (C99), если в некоторой единицы перевода функция определена как inline, а также объявленный как extern (используется явный extern), тогда встроенное определение этой функции также служит внешним определением. Если в блоке трансляции нет деклараций с явным extern, тогда встроенное определение используется только как "внутреннее" определение.

P.S. В С++ существует такая вещь, как extern "C", но это совершенно другое дело.

Ответ 2

В заголовочных файлах библиотеки C следует объявить функции:

extern void f();
// or only
void f();

Проблема 1: Семантика

В программе на С++ функции объявляются как функции, не возвращающие значения и не принимающие аргументов.

В программе C функции объявляются как функции, не возвращающие значения и принимающие неопределенный, но не переменный список аргументов.

Чтобы получить значение "без аргументов" в C, используйте один из:

extern void f(void);
void f(void);

То же самое обозначение также означает то же самое в С++, хотя для чистого кода на С++ использование void в списке аргументов не является идиоматическим (не делайте этого в чистом С++-коде).

Проблема 2: взаимодействие между C и С++

Трудно, но нормальное правило должно было бы объявить функции С++-кодом как 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, так и С++.

Макросы обычно определяются в одном универсальном заголовке, который используется повсюду, а затем конкретный заголовок гарантирует включение заголовка общего назначения, а затем использует соответствующую форму макроса.

Проблема 3: Стиль

Формально, нет необходимости в обозначении extern перед объявлением функции. Однако я использую его в заголовках, чтобы подчеркнуть, что это объявление функции, определяемой извне, и для симметрии с теми (редко) случаями, когда есть глобальная переменная, объявленная в заголовке.

Люди могут и не соглашаются с этим; Я использую локальные правила, но когда я являюсь создателем правил, extern включен в заголовок.

Ответ 3

Для общего использования объявляйте как

#ifdef __cplusplus
extern "C" {
#endif
  void f(void);
#ifdef __cplusplus
}
#endif

В противном случае extern устарел.

Ответ 4

Последнее прекрасно, поскольку это только определение функции, которое сообщает тем, кто включает этот заголовок: "Там есть функция с этим прототипом где-то здесь"

В этом контексте функции явно отличаются от переменных, но это другое дело. Однако убедитесь, что вы не включаете тело функции, если вы не объявляете его "inline" или частью определения класса (С++) или как "функция шаблона" (также С++).

Ответ 5

Задание extern в прототипе функции не влияет, поскольку по умолчанию предполагается. Всякий раз, когда компилятор видит прототип, он предполагает, что функция определена где-то в другом (в текущей или другой единицы перевода). Это выполняется для обоих языков.

В следующем потоке есть некоторые полезные комментарии в целом об extern.

Влияние ключевого слова extern на функции C