внешняя и внешняя «C»; для переменных

Я пишу разделяемую библиотеку C ++ для использования на C-программе. Тем не менее, у меня есть вопрос о extern а также extern "C",

Рассмотрим следующий код

Мой заголовочный файл выглядит так:

#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif

Это прекрасно работает; Я просто должен объявить

int global;

в моем .cpp или в моем .c файле. Однако я не понимаю:

В чем разница между extern "C" а также extern Вот? Я пытался комментировать extern "C" int global и это работает! Зачем?

я знаю это extern "C" используется для создания связей С Вот почему у меня extern "C" int addnumbers(int,int), Другими словами, если я хочу написать функцию C ++, которая должна использоваться в программе на C, я пишу extern "C", Теперь, что насчет глобальных переменных — я думаю, здесь другая ситуация? Я хочу, чтобы программа C использовала переменную C ++ с именем global, но я могу использовать extern не extern "C", Это почему? Это не интуитивно для меня.

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

4

Решение

Прикрепляя extern "C" к своим объявлениям C ++ (как к объектам, так и к функциям) вы даете им «связь C» — делайте их доступными из кода C. Если вы пропустите эту спецификацию «языковой связи», компилятор не будет прилагать никаких усилий для правильной связи. В случае функций это приводит к неудачной связи из-за искажения. В случае глобальных переменных все может работать нормально, потому что переменные не требуют искажения.

Однако в моей системе (MS Visual Studio) связь между C и C ++ не работает, если я «забываю» указать extern "C" спецификация связи в заголовочном файле C ++. Пример сообщения об ошибке:

error LNK2001: unresolved external symbol "int global" (?_global)

Хотя, когда я рассматриваю скомпилированный исходный код C ++, который содержит определение global с dumpbin Утилита, я вижу

00B 00000014 SECT4  notype       External     | ?global@@3HA (int global)

Таким образом, MS Visual Studio обрабатывает имена глобальных переменных, если они не имеют связи C — это делает спецификации связи C обязательными.


Кроме того, рассмотрим следующий пример:

namespace example {
int global;
}

Если глобальная переменная находится внутри пространства имен, код C не получит к ней доступ. В этом случае все компиляторы будут требовать правильной спецификации связи в объявлении C ++:

namespace example {
extern "C" int global;
}

Заключение:

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

8

Другие решения

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

в то время как extern "C" Это, как прокомментировали несколько человек, используется для решения проблемы искажения имени в C ++, эта функция будет называться addnumbers_i_i (или что-то подобное) компоновщиком, а в c его символ addnumbers

2

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

В C ++ нет стандарта для имен функций, сгенерированных компилятором. Ключевое слово extern «C» указывает компилятору генерировать имя функции в стандарте C.

0

Я нахожу, что extern «C» используется для компиляции функции C ++ в стандарте C, и это не относится к переменным, поскольку решения имени функции в C и C ++ различны. Например, «void foo (int x, int y)», компилятор C переведет его в «_foo», а компилятор C ++ переведет его в «_foo_int_int».

0
По вопросам рекламы [email protected]