2016-07-01 11 views
2

Я пишу общую библиотеку C++ для используемой программы C. Однако у меня есть вопрос о extern и extern "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" используется для соединения C. Вот почему у меня есть extern "C" int addnumbers(int,int). Другими словами, если я хочу написать C++-функцию, которая будет использоваться в программе C, я пишу extern "C". Теперь, как насчет глобальных переменных - ситуация здесь, я думаю? Я хочу, чтобы программа C использовала переменную C++ с именем global, но я могу использовать extern не extern "C". Почему это? Это неинтересно для меня.

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

+1

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

+0

Я приглашаю вас сделать это намного яснее в вашем вопросе. –

+0

Несмотря на то, что я изо всех сил пытаюсь обнаружить разницу между тем, какая разница между «extern» C »и« extern'_ »и« какая разница между «extern» C »и« extern »для переменных_. Возможно, вопрос заключается в том, что «extern» C «отличается при использовании для функций vs переменными? _, А ответ просто« нет » –

ответ

-1

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

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

-1

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

1

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

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

5

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

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

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

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

00B 00000014 SECT4 notype  External  | [email protected]@3HA (int global) 

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


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

namespace example { 
    int global; 
} 

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

namespace example { 
    extern "C" int global; 
} 

Вывод:

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