Domanda

sto prendendo un corso di linguaggi di programmazione e stiamo parlando della dichiarazione extern "C".

Come funziona questa dichiarazione lavoro a un livello più profondo diverso da "si interfaccia C e C ++"? In che modo incide le associazioni che si svolgono nel programma così?

È stato utile?

Soluzione

extern "C" viene utilizzato per garantire che i simboli seguenti non sono mutilato (decorato).


Esempio:

Diciamo che abbiamo il seguente codice in un file chiamato test.cpp:

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

int bar() {
  return 1;
}

Se si esegue gcc -c test.cpp -o test.o

Date un'occhiata ai nomi simboli:

  

00000010 T _Z3barv

     

00000000 T foo

foo() mantiene il suo nome.

Altri suggerimenti

Diamo un'occhiata a una funzione tipica che può compilare sia in C e C ++:

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

Ora, nel C la funzione viene chiamata "_ADD" internamente. Mentre la funzione C ++ si chiama qualcosa di completamente diverso internamente con un sistema chiamato nome-mutilazione. La sua fondamentalmente un modo per citarne funzione in modo che la stessa funzione con differenti parametri ha un nome interno diverso.

Quindi, se Aggiungi () è definito in add.c, e si dispone il prototipo in add.h otterrete un problema se si tenta di includere add.h in un file C ++. Poiché il codice C ++ è alla ricerca di una funzione con un nome diverso da quello in add.c si otterrà un errore di linker. Per ovviare a questo problema è necessario includere add.c con questo metodo:

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

Ora il codice C ++ si collegherà con _ADD al posto del nome della versione ++ storpiato C.

Questo è uno degli usi dell'espressione. Linea di fondo, se è necessario compilare il codice che è strettamente C in un programma C ++ (tramite un'istruzione include o altri mezzi) è necessario avvolgerlo con un extern "C" {...} dichiarazione.

Quando si contrassegna un blocco di codice con extern "C", che stai dicendo al sistema di utilizzare lo stile collegamento C.

Questo, soprattutto, colpisce il modo in cui il linker storpia i nomi. Invece di utilizzare C ++ nome dello stile pressare (che è più complessa di sostenere sovraccarichi operatore), si ottiene la denominazione standard in stile C fuori dal linker.

In C ++ il nome / simbolo delle funzioni sono in realtà rinominati a qualcos'altro tale che diverse classi / spazi dei nomi possono avere funzioni stesse firme. In C, le funzioni degli globalmente definiti e non è necessaria tale processo rinomina personalizzato.

Per rendere C ++ e C colloquio con l'altro, "C extern" istruisce il compilatore di non utilizzare la convenzione C.

Si dovrebbe notare che extern "C" modifica inoltre i tipi di funzioni. Non solo modificare le cose su livelli più bassi:

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

void foo();

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

Il tipo di &foo non è uguale al tipo che le designa typedef (anche se il codice viene accettato da alcuni, ma non tutti i compilatori).

extern C colpisce nome mangling dal compilatore C ++. Il suo un modo di ottenere il compilatore C ++ di non mangle nomi, o meglio a storpiare loro nello stesso modo in cui un compilatore C avrebbe fatto. Questo è il modo in cui si interfaccia C e C ++.

Per fare un esempio:

extern "C" void foo(int i);

consentirà la funzione di essere implementato in un modulo C, ma permettono di essere chiamato da un modulo C ++.

Il problema viene quando si cerca di ottenere un modulo C per chiamare una funzione C ++ (ovviamente C non può utilizzare le classi C ++) definita in un modulo C ++. Il compilatore C non piace extern "C".

Quindi, è necessario utilizzare questo:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Ora, quando questo appare in un file di intestazione, sia i compilatori C e C ++ saranno felici con la dichiarazione e potrebbe ora essere definita sia in un modulo C o C ++, e possono essere chiamati da entrambi C e C ++.

extern "C" indica che il codice racchiuso utilizza linking in stile C e il nome mangling. C ++ utilizza un nome mangling formato più complessa. Ecco un esempio:

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

int example(int alpha, char beta);

in C: _example

in C ++: __Z7exampleic

Aggiornamento:. Come GManNickG nota nei commenti, il modello di nome storpiatura è compilatore dipendente

extern "C", è una parola chiave per dichiarare una funzione con attacchi C, perché compilatore C e C ++ si tradurranno sorgente in forma diversa nel file oggetto:

Per esempio, un frammento di codice è la seguente:

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

compilatori a 32 bit C tradurranno il codice nella forma come segue:

_func1
_func2@4
@func3@4

nel cdecl, func1 sarà tradurre come ' _name '

nel stdcall, func2 sarà tradurre come ' _name @ X '

nel fastcall, func2 sarà tradurre come ' @ nome @ X '

' X ' significa che le quanti byte dei parametri nella lista dei parametri.

convenzione a 64 bit su Windows non ha nessuna sottolineatura

In C ++, vengono introdotte le classi, i modelli, gli spazi dei nomi e l'overload degli operatori, dal momento che non è consentito due funzioni con lo stesso nome, compilatore C ++ fornire le informazioni digitare il nome del simbolo,

Ad esempio, un frammento di codice è la seguente:

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

compilatore C ++ si tradurrà il codice come segue:

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' e '_I' sono informazioni sul tipo di 'vuoto' e 'int'

Ecco una citazione da MSDN

"La parola chiave extern dichiara una variabile o una funzione e specifica che ha linkage esterno (il suo nome è visibile da file diversi da quello in cui è definito). Quando si modifica una variabile, extern specifica che la variabile ha una durata statica ( essa è allocata quando il programma inizia e deallocato quando il programma termina). la variabile o funzione possono essere definiti in un'altra sorgente, o successiva nello stesso file. dichiarazioni di variabili e funzioni nell'ambito di file sono esterni di default. "

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top