In C++ (come in C), prima che il compilatore inizi a tradurre un file sorgente, viene attivato un programma, detto preprocessore. Come suggerisce il nome, il preprocessore effettua un'elaborazione preliminare del file sorgente, prima della compilazione vera e propria.
In pratica il preprocessore ricerca nel file sorgente speciali istruzioni, chiamate direttive. Una direttiva inizia sempre con il carattere # e occupa una sola riga. Alcuni esempi di direttive sono:
Il file sorgente contenente le direttive, viene tradotto dal preprocessore in quella che viene chiamata la translation unit. In pratica una translation unit è un file sorgente (che deve dunque ancora essere compilato) in cui le direttive sono state sostituite dal codice vero e proprio.
La direttiva #define consente di assegnare un nome a una costante. Ad esempio:
Questo significa che il preprocessore sostituisce ogni occorrenza della parola PIGRECO all'interno del programma col valore 3.14159. Per esempio i seguenti due programmi sono del tutto equivalenti in C++:
#include <cstdlib> #include <iostream> using namespace std; #define PIGRECO 3.14159 int main(int argc, char *argv[]) { double raggio, perimetro; cout<<"Inserire raggio del cerchio: "; cin>>raggio; perimetro=2*PIGRECO*raggio; cout<<"Il perimetro vale "<<perimetro; system("PAUSE"); return EXIT_SUCCESS; } |
#include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { double raggio, perimetro; cout<<"Inserire raggio del cerchio: "; cin>>raggio; perimetro=2*3.14159*raggio; cout<<"Il perimetro vale "<<perimetro; system("PAUSE"); return EXIT_SUCCESS; } |
La sintassi della direttiva #define è la seguente
Il nome della costante viene di solito scritto in maiuscolo per distinguerlo dalle variabili, ma non è obbligatorio. Di solito la direttiva #define viene scritta all'inizio del file, fuori dal main, ma può essere inserita ovunque, purché prima dell'uso effettivo della costante stessa.
Definire le costanti è utile in quanto consente di modificare rapidamente e senza possibile dimenticanze un valore ripetuto più volte in un programma. Si consideri per esempio il caso seguente:
Se si vuole cambiare le dimensioni del vettore, è sufficiente modificare la definizione della costante MAXDIM e automaticamente il cambiamento viene effettuato in tutto il programma.
Un modo più interessante di usare la direttiva #define è quello che consente di definire una macro. Una macro in C++ è un piccolo frammento di codice con un nome e dei parametri. Per esempio:
Si osservi la definizione della macro:
Il nome della macro è quadrato. Si notino le parentesi tonde dopo il nome e il parametro a (nome scelto liberamente) chiuso fra le parentesi. Il preprocessore in pratica espande
facendolo diventare
Le macro assomigliano molto alle funzioni, ma, a differenza di queste, non sono sottoprogrammi autonomi che vengono chiamati. Si tratta semplicemente di un meccanismo di sostituzione attuato dal preprocessore prima della compilazione vera e propria del programma.
Le macro sono generalmente più veloci delle funzioni (proprio perché non richiedono chiamata) ma presentano qualche rischio. Si consideri il seguente esempio:
L'esempio non fornisce il risultato corretto. Per esempio inserendo il valore 2 si ottiene come risultato che il quadrato di 3 è 5! Il motivo è che la riga contenente la macro viene espansa letteralmente nel seguente modo:
A causa della mancanza di parentesi e dell'ordine di precedenza sbagliato, il risultato che si ottiene è esso pure sbagliato. In questo caso il problema può essere risolto definendo la macro in questo modo:
Abbiamo già incontrato molte volte l'uso di questa direttiva, come per esempio in:
Il significato è molto semplice: il contenuto del file di testo di nome cstdlib viene copiato e incollato (incluso) nel punto in cui compare la direttiva all'interno del file sorgente. Il file si trova all'interno di una sottocartella all'interno della cartella di installazione di Dev-C++ (il percorso standard per i file include in C++ è Dev-Cpp/include e la sottocartella c++/3.4.2 dove l'ultimo numero indica la versione del programma).
I file include sono usati per contenere la definizione dei prototipi, delle macro, dei tipi e delle costanti utilizzate nelle funzioni di library del C++. Per esempio aprendo con un editor di testi il file math.h utilizzato per le funzioni della library matematica troviamo, fra le altre cose:
Qui possiamo riconoscere la definizione di una serie di costanti matematiche usate dalle funzioni. Si osservi a questo proposito che un file include può contenere al proprio interno altre direttive!
La direttiva #include può essere usata anche in questo modo:
In questo caso il file di nomefile scritto fra virgolette viene cercato nella cartella corrente del programma (e non nella cartella di sistema). Quest'uso può essere utile quando si voglia scrivere un proprio file include da usare insieme a un dato programma (per esempio per includere rapidamente in testa a un programma tutti i prototipi delle funzioni chiamate e tutte le costanti usate dal programma stesso).
Le direttive condizionali servono per fare compilare certe parti del programma in dipendenza dal verificarsi o meno di determinate condizioni. Per esempio:
#define COUNTRY ITALY
#if COUNTRY==ITALY
char
moneta[]="euro";
#elif CONTRY==US
char
moneta[]="dollar";
#else
char
moneta[]="pound";
#endif
In questo caso, a seconda del valore della costante COUNTRY, il vettore di caratteri moneta viene inizializzato con un valore diverso.
Senza voler approfondire troppo l'argomento, che è piuttosto complesso, segnaliamo qui un uso frequente delle direttive condizionali allo scopo di commentare una porzione di programma. Spesso quando si testa un programma si ha bisogno di "eliminare" temporaneamente parti del programma, in modo da verificare il funzionamento del resto.
Di solito questa cancellazione temporanea può essere fatta commentando la porzione di codice da eliminare, come nel seguente esempio:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int divisore, numero, resto;
cout<<"Fornisci un numero: ";
cin>> numero;
divisore=2;
/* while (divisore<numero)
{
resto = numero%divisore;
if (resto==0)
{
cout<<"Il
numero "<<numero<<" non e' primo\n";
break;
}
divisore = divisore+1;
}
*/
if (divisore == numero) /* se il ciclo è arrivato a
conclusione */
cout<<"Il numero "<<numero<<" e'
primo\n";
system("PAUSE");
return EXIT_SUCCESS;
}
La parte commentata (in rosso) è stata temporaneamente eliminata dal programma. Il problema di questa soluzione è che i commenti non possono contenere al proprio interno altri commenti. In altre parole, non si può eliminare con un commento una porzione di programma che già contenga un commento. Si consideri l'esempio che segue:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int divisore, numero, resto;
cout<<"Fornisci un numero: ";
cin>> numero;
divisore=2;
while (divisore<numero)
{
resto = numero%divisore;
if (resto==0)
{
cout<<"Il
numero "<<numero<<" non e' primo\n";
break;
}
divisore = divisore+1;
}
/* if (divisore == numero)
/* se il ciclo è arrivato a conclusione */
cout<<"Il numero "<<numero<<" e'
primo\n";
*/
system("PAUSE");
return EXIT_SUCCESS;
}
Il commento indicato in rosso non viene accettato in quanto contiene al proprio interno un altro commento e dunque non può essere interpretato correttamente dal compilatore.
In questi casi si adotta in genere la seguente soluzione:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int divisore, numero, resto;
cout<<"Fornisci un numero: ";
cin>> numero;
divisore=2;
while (divisore<numero)
{
resto = numero%divisore;
if (resto==0)
{
cout<<"Il
numero "<<numero<<" non e' primo\n";
break;
}
divisore = divisore+1;
}
#ifdef NODEF
if (divisore == numero) /* se il ciclo è arrivato
a conclusione */
cout<<"Il numero "<<numero<<" e'
primo\n";
#endif
system("PAUSE");
return EXIT_SUCCESS;
}
NODEF è un nome (scelto a caso, ma in modo esplicativo) di una costante che non è definita da nessuna parte nel programma. La direttiva condizionale #ifdef specifica che quella parte di programma dev'essere compilata solo se è definita la costante NODEF. Ma dal momento che questa costante non è stata definita, il risultato pratico è quello di escludere dalla compilazione la parte racchiusa fra #ifdef e #endif.
precedente - successiva
Sito realizzato in base al template offerto da
http://www.graphixmania.it