Pagina didattica di G. Servizi
Home >> Linguaggio C++ >> vocabolario C++


livello medio

extern

Questa parola del vocabolario ha due significati abbastanza diversi tra loro: il primo vale sia in ANSI C sia in C++, il secondo solo in C++. Cominciando da questo secondo significato e usando la seguente sintassi

extern "C" {
void funz1(.......);
int funz2(......);
....;
....;
....;
}


si istruisce il linker del compilatore C++ a eseguire il suo ufficio, su tutte le funzioni una cui dichiarazione è inserita nell'ambito lì presente, come se fossero state da compilare da parte del compilatore ANSI C, data la stringa "C" che segue immediatamente la parola extern. Se al posto di "C" fosse scritta una stringa contenente il nome di un altro linguaggio riconosciuto dal compilatore C++, lo si istruirebbe a dissimularsi come compilatore di quel linguaggio e a far eseguire il link di quelle funzioni come farebbe il compilatore di quel linguaggio (GRAN LINGUAGGIO !).

Ovviamente questa prerogativa serve soltanto se è necessario linkare codici misti, ossia dei propri programmi scritti in C++ assieme a librerie precompilate da chissà quale altro linguaggio. Per chi fosse interessato, è in questo modo che viene compilata, ad esempio, la sorgente di passe_par_tout e tutti i programmi degli utenti che includono il documento passe_par_tout.h


Per quanto riguarda il primo significato, extern si usa per qualificare delle dichiarazioni di variabili compiute nell'ambito globale di un certo documento sorgente e, nel C++, ANCHE all'interno di un namespace, per significare che la loro collocazione in memoria è quella di una variabile omonima dichiarata nell'ambito globale di un altro documento sorgente, o comunque all'esterno del namespace. Un paio di esempi chiarirà i concetti.

Esempio 1:

si considerino i seguenti due documenti sorgente:

1) documento 1: "file1.C"


#include <iostream>
using namespace std;
extern double x[  ];
void funz1(  )
{
for(int i=0; i < 10; ++i)
cout << x[i] << endl;}


2) documento 2: "file2.C"


#include <iostream>
using namespace std;
double x[10];

int main(  )
{
void funz1(  );
cout << " scrivi 10 numeri reali\n";
for(int i=0; i < 10; ++i)
cin >> x[i];
cout << "ecco i numeri che ho letto\n";
funz1(  );
}

La dichiarazione double x[ ]; nel documento 1 è necessaria affinché il compilatore non si lagni nel momento in cui incontra la linea cout/*omissis*/ nella funzione funz1. Tuttavia la lunghezza dell'array non è necessaria, anzi, è proprio MEGLIO non metterla, onde evitare rischi di contraddizione, mercé la parola extern che rassicura il compilatore comunicandogli che potrà demandare la ricognizione di tale lunghezza alla compilazione di qualche altra sorgente. In effetti x è debitamente ridichiarato nel documento 2 e a questo punto il linker riconosce che si tratta dello stesso array lasciato in sospeso dopo la compilazione del documento 1. Si osservi che in main è anche necessario dichiarare la funzione funz1, dato che la sua definizione non si trova nello stesso documento sorgente.


Esempio 2:

# include <iostream>
using namespace std;

namespace mio
{
extern double x[  ];
}

double mio::x[  ]{1.0, 2.0, 3.0};

int main(  )
{
for(auto i : mio::x) cout << i << ' ';
cout << endl;
}


Il programma presentato funziona solo grazie all'uso di extern; se lo si rimovesse occorrerebbe anche rimuovere l'inizializzazione in ambito globale e aggiungere esplicitamente la lunghezza richiesta per l'array al momento della sua dichiarazione.

Torna in cima alla pagina