Требуется, чтобы это добавляет 'экстерна C' в исходном файле также?

Я недавно нашел некоторый код, где экстерн "C" был добавлен в исходном файле также для функций. Они были также добавлены в заголовочных файлах, где они были объявлены.

Я находился под предположением, что добавление 'экстерна "C" в заголовочных файлах было достаточно.

Где должен экстерн "C" блоки быть добавленным?

ОБНОВЛЕНИЕ: Предположим, что я компилирую свой код C с помощью компилятора CPP и добавил экстерна "C" защита для всех функций в заголовочных файлах (т.е. все мои функции имеют свои прототипы в заголовках), но в исходных файлах я не добавил то же. Это вызовет проблему?

26
задан jalf 31 January 2010 в 14:59
поделиться

6 ответов

Поскольку вы имеете в виду

extern "C" { ... }

стилей охранников, они объявляют некоторые функции, чтобы быть «C» связи, а не «C ++» связи (которые обычно имеют кучу дополнительного украшения имени для поддержки вещей как перегруженные функции).

Цель, конечно, состоит в том, чтобы позволить код C ++ в интерфейс с C-кодом C, который обычно находится в библиотеке. Если заголовки библиотеки не были написаны с учетом C ++, , то они не будут включать в себя Extern «C» охранников для C ++ .

Заголовок C, написанный с помощью C ++, будет включать в себя что-то вдоль строк

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

, чтобы программы C ++ видят правильную связь. Однако не все библиотеки были написаны с помощью C ++, поэтому иногда вам нужно сделать

extern "C" {
#include "myclibrary.h"
}

, чтобы получить правильную связь. Если файл заголовка предоставляется кем-то другим, то не очень хорошая практика, чтобы изменить его (потому что тогда вы не можете обновить его легко), поэтому лучше обернуть файл заголовка своей собственной охраной (возможно, в вашем собственном файле заголовка).

Внешний «C» не (AFAIK) ANSI C, поэтому не может быть включен в обычный C-код без предварительно воспроцессорных охранников.

В ответ на ваше редактирование:

Если вы используете компилятор C ++, и вы объявляете функцию как Extern «C» в заголовочном файле, вам не нужно также объявлять, что функция как Extern "C" в Файл реализации. Из секции 7.5 стандарта C ++ (упор мой):

, если две объявления одинакового Функция или объект Укажите разные спецификации связи (то есть Характеристики связи этих Декларации указывают другое строковые литералы), программа неинтересно, если указаны декларации в том же единице перевода, а одно определение правила применяется, если объявления появляются в Различные переводки. Кроме Для функций с ссылками C ++, Декларация функции без связи Спецификация не должна предшествовать Первая спецификация связи для этого функция. Функция может быть объявлена без спецификации связи после Явная спецификация связи имеет был виден; Связывание явно указано в предыдущей декларации не зависит от такой функции Декларация.

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

26
ответ дан 28 November 2019 в 07:22
поделиться

Им нужно только пойти во все, что включено другими исходными файлами.

С некоторые идиомы Вы найдете людей, включая исходные файлы.

8
ответ дан 28 November 2019 в 07:22
поделиться

Я не знаю, как делать флэш-взаимодействия (и мне также интересно), но для html/javascript можно использовать Chickenfoot .

И чтобы получить безголовый + скриптовый браузер, работающий на Linux, вы можете использовать Qt webkit library . Вот пример использования .

-121--1117543-

Конструктор копирования имеет следующую форму:

class example 
{
    example(const example&) 
    {
        // this is the copy constructor
    }
}

В следующем примере показано, где он вызывается.

void foo(example x);

int main(void)
{
    example x1; //normal ctor
    example x2 = x1; // copy ctor
    example x3(x2); // copy ctor

    foo(x1); // calls the copy ctor to copy the argument for foo

}
-121--3768770-

Они должны быть добавлены ко всем файлам, которые будут включены в другие файлы.

Обычно исходные файлы не включаются.

3
ответ дан 28 November 2019 в 07:22
поделиться

Вы имеете в виду препроцессоры 'extern c'? Они должны быть в определении функции, а также это влияет на то, как вызов функции хранится в скомпилированном двоичном коде. Это действительно необходимо, только если Вы связываете скомпилированный c++ с c, который скомпилирован как C (в отличие от c в .cpp файле).

2
ответ дан 28 November 2019 в 07:22
поделиться

Апология

Вопрос изменился, чтобы было гораздо яснее, о чем он спрашивал. Этот ответ касался первоначального вопроса, когда, по крайней мере, было спорным, обсуждался ли вопрос о защите от множественного включения в заголовочные файлы - вот что касается моего ответа. Очевидно, что если бы вопрос был столь же ясен тогда, как сейчас, я бы не представил этот ответ.


Оригинальный ответ

Нет, нет необходимости включать охранников и в код С.

Если в заголовочном файле "header.h" говорится:

#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
...
#endif

Тогда для файла исходного текста "source.c" совершенно безопасно говорить:

#include "header.h"

Для других заголовков также безопасно включать "header.h".

Однако, люди отмечают, что открытие заголовочного файла и его чтение занимает время, что замедляет компиляцию, поэтому иногда люди делают такие вещи, как:

#ifndef HEADER_H_INCLUDED
#include "header.h"
#endif

Это означает, что если в какой-то другой заголовок, включенный в 'source.c', уже был включен 'header.h', то '#include' не перерабатывается. (Или, если 'header.h' уже был включен непосредственно в 'source.c', хотя это глупый баглет)

Так что, когда мы сталкиваемся с этим, это, скорее всего, попытка оптимизировать производительность компиляции. Отнюдь не очевидно, что это многого стоит; современные препроцессоры на Си достаточно умны в этом вопросе и, если смогут, избегут повторного включения файла. И всегда есть риск, что тест в 'source.c' имеет опечатку (#ifndef HEARER_H_INCLUDED, возможно). В этом случае тест замедляет компиляцию, так как препроцессор тестирует несущественное условие, а затем все-таки переходит на включение 'header.h'. Это 'safe'; сам заголовок защищен-- или должен быть.

Если код в 'source.c' также содержит '#define HEADER_H_INCLUDED', то возникают проблемы. #define должен быть либо до, либо после #include, и ни то, ни другое не является хорошей общей методикой.

  • Если 'source.c' делает '#define HEADER_H_INCLUDED' до включения 'header.h', то если защита появится в 'header.h', то содержимое заголовка не будет включено. Если защита не появляется в 'header.h', то все работает нормально.
  • Если 'source.c' после включения 'header.h' делает '#define HEADER_H_INCLUDED', то если защита появляется в 'header.h', то мы получаем доброкачественное переопределение HEADER_H_INCLUDED. Если 'header.h' не содержит защитника, но включает в себя файл, который включает в себя 'header.h', то вы не защищены от многократного включения в конце концов.

Обратите внимание, что тело заголовка появляется после '#define HEADER_H_INCLUDED'. Это опять защита, если вложенный включает в себя 'header.h'.

2
ответ дан 28 November 2019 в 07:22
поделиться

Гвардии «C» имеют два целя:

  1. , когда ваш код скомпилирован, функции будут экспортированы таким образом, что позволит использовать компилятор / линкер Non C ++ их (no c ++ name mangling etc.)
  2. Когда компилятор C ++ использует ваши файлы заголовка, он будет знать, что он должен связать символы в порядке C, который, в свою очередь, убедитесь, что полученная программа будет успешно связана. Они не имеют смысла для компилятора Non C ++, но поскольку символы были генерированы в C-стиле в (1), это желаемый эффект.

Поскольку вы включаете заголовок с гвардейками «C», также в файле реализации, информация о том, как должна быть создана символы во время компиляции, доступна для компилятора, и компилятор создаст символы таким образом, что может быть используется компилятор без C ++. Следовательно, вам нужно только указать Extern «C» в файл заголовка, пока файл заголовка также включен файл реализации.

1
ответ дан 28 November 2019 в 07:22
поделиться