Jak działa deklaracja extern "C"?
Biorę udział w kursie języków programowania i mówimy o extern "C"
deklaracji.
Jak ta deklaracja działa na głębszym poziomie niż " interfejsy C i C++"? Jak to wpływa na wiązania, które odbywają się również w programie?
9 answers
extern "C"
służy do zapewnienia, że poniższe symbole nie są zniekształcone (dekorowane).
Przykład:
Załóżmy, że mamy następujący kod w pliku o nazwie test.cpp
:
extern "C" {
int foo() {
return 1;
}
}
int bar() {
return 1;
}
If you run gcc -c test.cpp -o test.o
Spójrz na nazwy symboli:
00000010 T _z3barv
00000000 T foo
foo()
zachowuje swoją nazwę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 18:00:15
Spójrzmy na typową funkcję, która może kompilować zarówno w C, jak i C++:
int Add (int a, int b)
{
return a+b;
}
Teraz w C funkcja nazywa się wewnętrznie "_Add". Natomiast funkcję C++ nazywa się czymś zupełnie innym wewnętrznie za pomocą systemu nazwanego namaglowaniem. To w zasadzie sposób na nazwanie funkcji tak, aby ta sama funkcja o różnych parametrach miała inną nazwę wewnętrzną.
Więc jeśli Add() jest zdefiniowane w add.c, i masz prototyp w dodatku.h będziesz miał problem, jeśli spróbujesz aby dodać.h w pliku C++. Ponieważ kod C++ szuka funkcji o nazwie innej niż ta w add.c otrzymasz błąd łącznika. Aby obejść ten problem, musisz dołączyć add.c tą metodą:
extern "C"
{
#include "add.h"
}
Teraz kod C++ połączy się z _Add zamiast z nazwą wersji mangled C++.
To jedno z zastosowań wyrażenia. Podsumowując, jeśli potrzebujesz skompilować kod, który jest ściśle C w programie C++ (za pomocą instrukcji include lub w inny sposób), możesz trzeba owinąć go z zewnątrz "C" {... deklaracja.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 17:56:54
Kiedy oznaczasz blok kodu extern "C", mówisz systemowi, aby używał połączenia w stylu C.
Wpływa to głównie na sposób, w jaki linker zniekształca nazwy. Zamiast używać mangling nazw w stylu C++ (co jest bardziej skomplikowane, aby obsługiwać przeciążenia operatorów), otrzymujesz standardowe nazewnictwo w stylu C z linkera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 18:16:21
W C++ nazwa/symbol funkcji jest zmieniana na coś innego, tak że różne klasy / przestrzenie nazw mogą mieć funkcje o tych samych podpisach. W języku C wszystkie funkcje są definiowane globalnie i nie jest potrzebny taki niestandardowy proces zmiany nazwy.
Aby C++ i C ze sobą rozmawiały, "extern C"nakazuje kompilatorowi nie używać konwencji C.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 18:14:40
Należy zauważyć, że extern "C"
modyfikuje również typy funkcji. Nie tylko modyfikuje rzeczy na niższych poziomach:
extern "C" typedef void (*function_ptr_t)();
void foo();
int main() { function_ptr_t fptr = &foo; } // error!
Typ &foo
nie jest równy typowi oznaczonemu przez typedef (chociaż kod jest akceptowany przez niektóre, ale nie wszystkie Kompilatory).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 21:39:37
Extern C wpływa na wymazywanie nazw przez kompilator C++. Jest to sposób na to, aby kompilator C++ nie zmieniał nazw, a raczej zmieniał je w taki sam sposób, jak kompilator C. W ten sposób łączy C i C++.
Jako przykład:
extern "C" void foo(int i);
Pozwoli na zaimplementowanie funkcji w module C, ale pozwoli na wywołanie jej z modułu C++.
Problem pojawia się przy próbie wywołania przez moduł C funkcji C++ (Oczywiście C nie może używać klas C++) zdefiniowanych w module C++. Kompilator C nie lubi extern "C"
.
Więc musisz użyć tego:
#ifdef __cplusplus
extern "C" {
#endif
void foo(int i);
#ifdef __cplusplus
}
#endif
Teraz, gdy to pojawi się w pliku nagłówkowym, zarówno kompilatory C i c++ będą zadowolone z deklaracji i może być teraz zdefiniowany w module C lub C++ i może być wywołany zarówno przez kod C i C++.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 18:06:09
Extern " C " oznacza, że załączony kod używa linkowania w stylu C i namaglowania nazw. C++ używa bardziej skomplikowanego formatu mangling nazw. Oto przykład:
Http://en.wikipedia.org/wiki/Name_mangling
int example(int alpha, char beta);
W C: _example
W C++: __Z7exampleic
Update: jak zauważa GManNickG w komentarzach, wzorzec manglingu nazw jest zależny od kompilatora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-08 16:08:13
Extern "C", jest słowem kluczowym do deklarowania funkcji z powiązaniami C, ponieważ kompilator C i kompilator C++ będą tłumaczyć źródło na inną formę w pliku obiektowym:
Na przykład fragment kodu jest następujący:
int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}
32-bitowe kompilatory C będą tłumaczyć kod w następujący sposób:
_func1
_func2@4
@func3@4
W cdecl func1 przetłumaczy jako ' _name '
Func2 w stdcall będzie tłumaczony jako ' _name@X 'W fastcall func2 będzie translate as ' @ name@X '
'X ' oznacza liczbę bajtów parametrów na liście parametrów.
64-bitowa Konwencja w systemie Windows nie ma wiodącego podkreślenia
W C++ wprowadzono klasy, szablony, przestrzenie nazw i przeciążenia operatorów, ponieważ nie są dozwolone dwie funkcje o tej samej nazwie, kompilator C++ dostarcza informacji o typie w nazwie symbolu,
Na przykład fragment kodu jest następujący:
int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}
Kompilator C++ będzie Przetłumacz kod w następujący sposób:
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' _i 'to informacje typu 'void ' i'int'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-30 13:42:01
Oto cytat z msdn
" słowo kluczowe extern deklaruje zmienną lub funkcję i określa, że ma ona odnośnik zewnętrzny (jej nazwa jest widoczna z plików innych niż ten, w którym została zdefiniowana). Podczas modyfikowania zmiennej, extern określa, że zmienna ma statyczny czas trwania (jest przydzielana, gdy program się rozpoczyna, a dealokowana, gdy program się kończy). Zmienna lub funkcja może być zdefiniowana w innym pliku źródłowym lub później w tym samym pliku. Deklaracje zmiennych i funkcje w zakresie plików są domyślnie zewnętrzne."
Http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 17:52:02