Как работает внешняя декларация «С»?

Я беру курс языков программирования, и мы говорим о extern "C" заявлении extern "C" .

Как это объявление работает на более глубоком уровне, кроме «он взаимодействует с C и C ++»? Как это влияет на привязки, которые происходят и в программе?

    extern "C" используется, чтобы гарантировать, что следующие символы не искалечены (украшены).


    Пример:

    Допустим, у нас есть следующий код в файле test.cpp :

     extern "C" { int foo() { return 1; } } int bar() { return 1; } 

    Если вы запустите gcc -c test.cpp -o test.o

    Взгляните на имена символов:

    00000010 T _Z3barv

    00000000 T foo

    foo() сохраняет свое имя.

    Давайте посмотрим на типичную функцию, которая может компилироваться как на C, так и на C ++:

     int Add (int a, int b) { return a+b; } 

    Теперь в C функция называется «_Add» внутренне. В то время как C ++-функция называется чем-то совершенно другим внутренне, используя систему, называемую man-ключ. Его в основном способ назвать функцию, так что одна и та же функция с разными параметрами имеет другое внутреннее имя.

    Поэтому, если Add () определен в add.c, и у вас есть прототип в add.h, у вас возникнет проблема, если вы попытаетесь включить add.h в файл C ++. Поскольку код C ++ ищет функцию с именем, отличным от имени в add.c, вы получите ошибку компоновщика. Чтобы обойти эту проблему, вы должны включить add.c этим методом:

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

    Теперь код C ++ будет ссылаться на _Add вместо имени C ++ с измененной версией.

    Это одно из применений выражения. Итог, если вам нужно скомпилировать код, который строго C в C ++-программе (с помощью оператора include или каких-либо других средств), вам нужно обернуть его с помощью выражения extern «C» {…}.

    Когда вы отмечаете блок кода с помощью extern «C», вы сообщаете системе использовать ссылку на стиль C.

    Это, в основном, влияет на то, как компоновщик управляет именами. Вместо того, чтобы использовать имя стиля стиля C ++ (что более сложно для поддержки перегрузок операторов), вы получаете стандартное именование C-стиля из компоновщика.

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

    Чтобы заставить C ++ и C разговаривать друг с другом, «extern C» инструктирует компилятор не использовать соглашение C.

    Следует отметить, что extern "C" также изменяет типы функций. Он не только модифицирует вещи на более низких уровнях:

     extern "C" typedef void (*function_ptr_t)(); void foo(); int main() { function_ptr_t fptr = &foo; } // error! 

    Тип &foo не равен типу, который обозначается typedef (хотя код принят некоторыми, но не всеми компиляторами).

    extern C влияет на изменение имени компилятором C ++. Его способ заставить компилятор C ++ не манипулировать именами, или, скорее, калечить их так же, как компилятор C. Так он взаимодействует с C и C ++.

    В качестве примера:

     extern "C" void foo(int i); 

    позволит реализовать функцию в модуле C, но разрешить ее вызывать из модуля C ++.

    Проблема возникает при попытке получить модуль C для вызова функции C ++ (очевидно, C не может использовать classы C ++), определенные в модуле C ++. Компилятор C не любит extern "C" .

    Поэтому вам нужно использовать это:

     #ifdef __cplusplus extern "C" { #endif void foo(int i); #ifdef __cplusplus } #endif 

    Теперь, когда это появляется в файле заголовка, компиляторы C и C ++ будут довольны объявлением, и теперь он может быть определен либо в C или C ++-модуле, и может быть вызван как кодом C, так и C ++.

    extern «C» означает, что вложенный код использует ссылку на C-стиль и название mangling. C ++ использует более сложный формат изменения имени. Вот пример:

    http://en.wikipedia.org/wiki/Name_mangling

     int example(int alpha, char beta); 

    в C: _example

    в C ++: __Z7exampleic

    Обновление: поскольку примечания GManNickG в комментариях, шаблон изменения имени зависит от компилятора.

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

    Например, fragment кода выглядит следующим образом:

     int _cdecl func1(void) {return 0} int _stdcall func2(int) {return 0} int _fastcall func3(void) {return 1} 

    32-битные компиляторы C преобразуют код в форму следующим образом:

     _func1 [email protected] @[email protected] 

    в cdecl func1 будет переводиться как ‘ _name

    в stdcall func2 будет переводиться как ‘ _name @ X

    в fastcall func2 будет переводиться как ‘ @ name @ X

    « X » означает количество байтов параметров в списке параметров.

    64-битная конвенция в Windows не имеет главного подчеркивания

    В C ++ вводятся classы, шаблоны, пространства имен и перегрузка операторов, поскольку для него не допускаются две функции с одинаковым именем, компилятор C ++ предоставляет информацию о типе в имени символа,

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

     int func(void) {return 1;} int func(int) {return 0;} int func_call(void) {int m=func(), n=func(0);} 

    Компилятор C ++ переводит код следующим образом:

     int func_v(void) {return 1;} int func_i(int) {return 0;} int func_call(void) {int m=_func_v(), n=_func_i(0);} 

    ‘_v’ и ‘_i’ – это информация типа ‘void’ и ‘int’

    Вот цитата из msdn

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

    http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

    Давайте будем гением компьютера.