Newsgroup: it.comp.lang.c++
Titolo: info sulle istruzioni del preprocessore

Sul mio libro ho trovato il seguente esempio, che non mi è per niente
chiaro.
#ifdef __cplusplus
extern "C" {        /* permette l'uso in c++ */
#endif
/* unità di traduzione */
#ifdef __cplusplus
}
#endif
Vorrei sapere: perchè viene aperta una graffa dopo la parola extern?
Soprattutto, perchè c'è #endif subito dopo la graffa aperta? Cos'è
__cpluplus e perchè ci sono i due trattini di sottolineatura?
Scusate la valanga di domande, ma il libro le butta lì senza un minimo di
spiegazione...
--
San Vegeta from Hell
http://www.geocities.com/Area51/Dungeon/8436
(da visitare con un browser della Netscape)

Le istruzioni a cui ti riferisci sono necessarie per forzare la generazione
dei nomi delle funzioni senza usare il name mangling, ovvero la generazione
del nome univoco in base al nome della funzione, il numero e il tipo di
argomenti etc che il compilatore C++ (non C) deve eseguire per gestire
l'overloading delle funzioni per permettere poi al linker di identificare
univocamente ogni singola funzione.
Questo e' necessario sia quando si deve chiamare una funzione C da C++
(l'esempio piu' utilizzato e' quello delle chiamate alla C runtime library )
dove il compilatore deve generare il tag con il nome della funzione da
chiamare senza applicare name mangling, oppure se si vogliono produrre
funzioni C++ (perdendo ovviamente l'overloading) richiamabili da moduli
compilati in C.
Attenzione:
extern "C" {  e' una keyword del C/C++ e viene gestita dal compilatore
mentre #ifdef che e' una direttiva viene gestita dal preprocessore.
Ovviamente esiste anche
extern "C++"
che fa' l'esatto contrario, cioe' attiva la generazione del name mangling
(generalmente non supportata dai compilatori C).
__cplusplus e' un identificatore predefinito solo per i preprocessori C++ di
conseguenza:
#ifdef __cplusplus
extern "C"
#endif
e
#ifdef __cplusplus
}
#endif
inserisce tutti i prototipi delle funzioni comprese nel namespace C (quando
vengono compilati in C++).
Quando lo stesso modulo viene compilato da C __cplusplus non e' definito e
di conseguenza i prototipi che seguono vengono trattati come al solito.
__cplusplus e' utile anche quando devi scrivere header che devono poter
essere compilati sia in C che in C++ ma che contengono keyword o estensioni
proprie del C++ (class,  template etc).
Buona lettura.

 __cpluplus e perchè ci sono i due trattini di sottolineatura?
__cplusplus e' una macro che' e' definita in C++ ma non in C.
Se si scrive:
  #ifdef __cplusplus
    // un po' di codice
  #endif
il codice all'interno dell'#ifdef viene visto dai compilatori C++
ma viene ignorato dai compilatori C.
extern "C"  prima di una dichiarazione di funzione indica al compilatore
che la funzione ha "C linkage" (compilata in C, niente name mangling, ...).
Questo permette di linkare librerie C in un programma C++.
Si possono raggruppare piu' dichiarazioni usando { e }:
  extern "C" {
    // varie dichiarazioni
    // ...
  }
I compilatori C non accettano extern "C" (e non ne hanno bisogno), quindi
si deve fare in modo che l'extern "C" e le graffe siano visti solo dai
compilatori C++:
  #ifdef __cplusplus
    extern "C" {
  #endif
 
    // ....
 
  #ifdef __cplusplus
    }
  #endif
Le #ifdef vengono gestite dal preprocessore (che se ne frega delle graffe),
quindi non ci sono problemi a chiudere l'#ifdef/endif senza chiudere la
graffa.
	Mauro

 Cos'è __cplusplus e perchè ci sono i due trattini di sottolineatura?
E' un simbolo che viene definito dai compilatori C++ ma non ricordo se è
uno standard o meno. I due trattini sono una convenzione per i nomi
riservati.
EMG