Comment fonctionne une déclaration "c" externe?

je prends un cours de langues de programmation et nous parlons de la extern "C" déclaration.

comment cette déclaration fonctionne-t-elle à un niveau plus profond que "it interfaces C et C++"? Comment cela affecte les liaisons qui ont lieu dans le programme?

22
demandé sur Jonathan Leffler 2010-03-08 20:49:59

9 réponses

extern "C" est utilisé pour s'assurer que les symboles suivants ne sont pas mutilé (décoré).


Exemple:

disons que nous avons le code suivant dans un fichier appelé test.cpp:

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

int bar() {
  return 1;
}

si vous courez gcc -c test.cpp -o test.o

regardez les noms des symboles:

00000010 T _Z3barv

00000000 t foo

foo() garde son nom.

44
répondu Bertrand Marron 2010-03-08 18:00:15

regardons une fonction typique qui peut compiler en C et C++:

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

Maintenant, en C la fonction est appelée "_Add" en interne. Tandis que la fonction C++ est appelée quelque chose de complètement différent à l'intérieur en utilisant un système appelé nom-mangling. C'est fondamentalement une façon de nommer une fonction de sorte que la même fonction avec des paramètres différents a un Nom interne différent.

donc si Add () est défini dans add.c, et vous avez le prototype en add.h, vous obtiendrez un problème si vous essayez d'inclure ajouter.h dans un fichier c++. Parce que le code C++ est à la recherche d'une fonction avec un nom différent de celui en ajouter.c vous obtiendrez une erreur de linker. Pour contourner ce problème, vous devez inclure ajouter.c par cette méthode:

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

maintenant le code C++ se liera avec _Add au lieu de la version de nom c++ mangée.

C'est l'une des utilisations de l'expression. En fin de compte, si vous avez besoin de compiler du code qui est strictement C dans un programme C++ (via un include déclaration ou un autre moyen) vous avez besoin de l'envelopper avec un "C" externe { ... } déclaration.

22
répondu Cthutu 2010-03-08 17:56:54

quand vous marquez un bloc de code avec un "C" externe, vous dites au système d'utiliser un lien de style C.

ceci, principalement, affecte la façon dont le linker coupe les noms. Au lieu d'utiliser le nom de style C++ mangling (qui est plus complexe pour supporter les surcharges d'opérateur), vous obtenez le nom de style C standard du linker.

9
répondu Reed Copsey 2010-03-08 18:16:21

en C++ le nom / symbole des fonctions est en fait renommé à quelque chose d'autre tel que différentes classes/namespaces peuvent avoir des fonctions de même signatures. Dans C, les fonctions sont toutes définies globalement et aucun processus de renommage personnalisé n'est nécessaire.

pour faire parler C++ et C l'un avec l'autre, "extern C" demande au compilateur de ne pas utiliser la convention C.

5
répondu gilbertc 2010-03-08 18:14:40

Il est à noter que extern "C" modifie également les types de fonctions. Ce n'est pas seulement de modifier des choses sur les niveaux inférieurs:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

le type de &foo n'est pas égal au type que le typedef désigne (bien que le code soit accepté par certains, mais pas par tous les compilateurs).

5
répondu Johannes Schaub - litb 2010-03-08 21:39:37

extern C affecte la modification du nom par le compilateur C++. Son un moyen d'obtenir le compilateur C++ de ne pas coder les noms, ou plutôt à la mutilation de la même manière qu'un compilateur C. C'est la façon dont il se connecte C et C++.

comme exemple:

extern "C" void foo(int i);

permettra à la fonction d'être implémentée dans un module C, mais permettra qu'elle soit appelée à partir d'un module C++.

le problème vient quand on essaie d'obtenir un module C pour appeler une fonction c++ (évidemment C ne peut pas utilisez les classes c++) définies dans un module c++. Le compilateur C n'aime pas extern "C".

vous devez donc utiliser ceci:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

lorsque cela apparaît dans un fichier d'en-tête, les compilateurs C et c++ seront satisfaits de la déclaration et celle-ci peut désormais être définie dans un module C ou C++, et peut être appelée à la fois par le code C et c++.

4
répondu quamrana 2010-03-08 18:06:09

extern "C" indique que le code ci-joint utilise la liaison de style C et la modification des noms. C++ utilise un format plus complexe pour la modification des noms. Voici un exemple:

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

int example(int alpha, char beta);

EN C:_example

EN c++:__Z7exampleic

mise à jour: comme le note GManNickG dans les commentaires, le pattern de nom mangling est dépendant du compilateur.

3
répondu Harvey 2014-07-08 16:08:13

extern "C", est un mot-clé pour déclarer une fonction avec des liaisons C, parce que le compilateur C et le compilateur C++ traduiront la source sous une forme différente dans le fichier objet:

Par exemple, un extrait de code est comme suit:

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

32 bits C compilateurs traduire le code dans le formulaire comme suit:

_func1
_func2@4
@func3@4

dans le cdecl, func1 se traduira par'_name'

dans le stdcall, func2 se traduit par ' _name@x'

dans le fastcall, func2 se traduira par'@nom@X'

' X " signifie le nombre d'octets de paramètres dans la liste des paramètres.

64 bits convention sur Windows n'a aucun trait de soulignement

en C++, Les classes, les gabarits, les namespaces et la surcharge de l'opérateur sont introduits, puisqu'il n'est pas permis deux fonctions avec le même nom, C++ compiler fournir l'information de type dans le symbole nom,

par exemple, un extrait de code est comme suit:

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

C++ compilateur traduit le code comme suit:

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' et '_i' sont des informations de type "void" et "int"

0
répondu Dongwei Wang 2015-04-30 13:42:01

Voici une citation de msdn

" le mot clé externe déclare une variable ou une fonction et spécifie qu'elle a un lien externe (son nom est visible à partir de fichiers autres que celui dans lequel elle est définie). Lors de la modification d'une variable, extern spécifie que la variable a une durée statique (elle est affectée lorsque le programme commence et désallouée lorsque le programme se termine). La variable ou la fonction peut être définie dans un autre fichier source, ou plus tard dans le même fichier. Les déclarations de les variables et les fonctions à la portée du fichier sont externes par défaut."

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

-2
répondu Joe Pitz 2010-03-08 17:52:02