Question

Je prends un cours de langage de programmation et nous parlons du extern "C" déclaration.

Comment cette déclaration fonctionne-t-elle à un niveau plus profond autre que "il interface C et C ++"? Comment cela affecte-t-il également les liaisons qui se déroulent également dans le programme?

Était-ce utile?

La solution

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

Jetez un œil aux noms des symboles:

00000010 T _Z3BARV

00000000 T foo

foo() garde son nom.

Autres conseils

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 en interne à l'aide d'un système appelé name-manmangling. C'est essentiellement un moyen de nommer une fonction afin que la même fonction avec différents paramètres ait un nom interne différent.

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

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

Maintenant, le code C ++ sera lié à _ADD au lieu de la version mutilée du nom C ++.

C'est l'une des utilisations de l'expression. Conclusion, si vous avez besoin de compiler du code strictement C dans un programme C ++ (via une instruction Inclure ou d'autres moyens), vous devez l'envelopper avec une déclaration externe "C" {...}.

Lorsque vous signalez un bloc de code avec "C" externe, vous dites au système d'utiliser la liaison de style C.

Cela affecte principalement la façon dont le linker gère les noms. Au lieu d'utiliser le mangling de nom de style C ++ (qui est plus complexe pour prendre en charge les surcharges de l'opérateur), vous obtenez la dénomination standard de style C de l'éditeur de liens.

En C ++, le nom / symbole des fonctions est réellement renommé quelque chose de tel que différentes classes / espaces de noms peuvent avoir des fonctions de même signatures. En C, les fonctions sont toutes définies à l'échelle mondiale et aucun processus de changement de nom personnalisé n'est nécessaire.

Pour faire C ++ et C parler les uns avec les autres, "Extern C" demande au compilateur de ne pas utiliser la convention C.

Il convient de noter que extern "C" Modifie également les types de fonctions. Il ne modifie pas seulement les choses à des 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'égale pas le type que le typedef désigne (bien que le code soit accepté par certains, mais pas tous des compilateurs).

extern c affecte le nom de nom par le compilateur C ++. C'est une façon d'amener le compilateur C ++ à ne pas gâter les noms, ou plutôt à les manquer de la même manière qu'un compilateur C le ferait. C'est ainsi qu'il interface C et C ++.

Par exemple:

extern "C" void foo(int i);

permettra à la fonction d'être implémentée dans un module C, mais permettez-le à l'appeler à partir d'un module C ++.

Le problème vient lorsque vous essayez d'obtenir un module C pour appeler une fonction C ++ (évidemment C ne peut pas utiliser 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

Maintenant, lorsque cela apparaît dans un fichier d'en-tête, les compilateurs C et C ++ seront satisfaits de la déclaration et il pourrait maintenant être défini dans un module C ou C ++, et peut être appelé par le code C et C ++.

Extern "C" indique que le code fermé utilise la liaison de style C et le mangling. C ++ utilise un format de mangling de nom plus complexe. 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 Gmannickg le note dans les commentaires, le modèle de mangling est dépendant du compilateur.

Extern "C", est un mot-clé pour déclarer une fonction avec C Bindings, car C compilateur et le compilateur C ++ traduireont la source sous une forme différente dans le fichier d'objet:

Par exemple, un extrait de code est le suivant:

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

Les compilateurs C 32 bits traduiront le code sous la forme comme suit:

_func1
_func2@4
@func3@4

Dans le CDECL, Func1 se traduira par '_Nom'

Dans le stdcall, Func2 se traduira par '_name @ x'

Dans le FastCall, Func2 se traduira par '@ name @ x'

'X«signifie combien d'octets des paramètres dans la liste des paramètres.

La convention 64 bits sur Windows n'a pas de soulignement leader

En C ++, les classes, les modèles, les espaces de noms et la surcharge de l'opérateur sont introduits, car il n'est pas autorisé deux fonctions avec le même nom, le compilateur C ++ fournit les informations de type dans le nom du symbole,

Par exemple, un extrait de code est le suivant:

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

Le compilateur C ++ traduira 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 de 'void' et 'int'

Voici une citation de MSDN

"Le mot-clé externe déclare une variable ou une fonction et spécifie qu'elle a une liaison externe (son nom est visible à partir de fichiers autres que celui dans lequel il est défini). Lors de la modification d'une variable, Extern spécifie que la variable a une durée statique (il est alloué Lorsque le programme commence et traité à la fin du programme). La variable ou la fonction peut être définie dans un autre fichier source, ou ultérieurement dans le même fichier. Les déclarations de variables et de fonctions à la portée du fichier sont externes par défaut. "

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top