Ogni programma scritto in un qualsiasi linguaggio di programmazione
prima di essere eseguito viene sottoposto ad un processo di compilazione o
interpretazione (a seconda che si usi un compilatore o un interprete). Lo scopo di
questo processo e` quello di tradurre il programma originale (codice sorgente) in
uno semanticamente equivalente, ma eseguibile su una certa macchina. Il processo di
compilazione e` suddiviso in piu` fasi, ciascuna delle quali volta all'acquisizione
di opportune informazioni necessarie alla fase successiva.
La prima di queste fasi e` nota come analisi lessicale ed ha il compito di
riconoscere gli elementi costitutivi del linguaggio sorgente, individuandone anche
la categoria lessicale. Ogni linguaggio prevede un certo numero di categorie
lessicali e in C++ possiamo distinguere in particolare le seguenti categorie:
I commenti, come in qualsiasi altro linguaggio, hanno
valore soltanto per il programmatore e vengono ignorati dal compilatore.
E` possibile inserirli nel proprio codice in due modi diversi:
secondo lo stile C ovvero racchiudendoli tra i simboli /* e */
facendoli precedere dal simbolo //
Nel primo caso e` considerato commento tutto quello che e` compreso tra /*
e */, il commento quindi si puo` estendere anche su piu` righe o trovarsi
in mezzo al codice:
void Func() {
...
int a = 5; /* questo e` un commento
diviso su piu` righe */
a = 4 /* commento */ + 5;
...
}
Nel secondo caso, proprio del C++, e` invece considerato commento tutto cio` che
segue // fino alla fine della linea, ne consegue che non e` possibile
inserirlo in mezzo al codice o dividerlo su piu` righe (a meno che anche l'altra
riga non cominci con //):
void Func() {
...
int a = 5; // questo e` un commento valido
a = 4 // sbagliato, il "+ 5;" e` considerato commento + 5;
e non e` possibile dividerlo su piu` righe
...
}
Benche` esistano due distinti metodi per commentare il codice, non e` possibile
avere commenti annidati, il primo simbolo tra // e /* determina il
tipo di commento che l'analizzatore lessicale si aspetta. Bisogna anche ricordare
di separare sempre i caratteri di inizio commento
dall'operatore di divisione (simbolo /):
a + c //* commento */ 3
Tutto cio` che segue "a + c" viene interpretato come un commento iniziato da //,
e` necessario inserire uno spazio tra / e /*.
Gli identificatori sono simboli definiti dal
programmatore per riferirsi a cinque diverse categorie di oggetti:
Variabili;
Costanti simboliche;
Etichette;
Tipi definiti dal programmatore;
Funzioni;
Le variabili sono contenitori di valori di un qualche tipo; ogni variabile puo`
contenere un singolo valore che puo` cambiare nel tempo, il tipo di questo valore
viene comunque stabilito una volta per tutte e non puo` cambiare.
Le costanti simboliche servono ad identificare valori che non cambiano nel tempo,
non possono essere considerate dei contenitori, ma solo un nome per un valore.
Una etichetta e` un nome il cui compito e` quello di identificare una istruzione
del programma e sono utilizzate dall'istruzione di salto incondizionato
goto.
Un tipo invece, come vedremo meglio in seguito,
identifica un insieme di valori e di operazioni definite su questi valori; ogni
linguaggio (o quasi) fornisce un certo numero di tipi primitivi (cui e` associato
un identificatore di tipo predefinito) e dei meccanismi per permettere la
costruzione di nuovi tipi (a cui il programmatore deve poter associare un nome)
a partire da questi.
Infine, funzione e` il termine che il C++ utilizza per indicare i sottoprogrammi.
Parleremo comunque con maggior dettaglio di variabili, costanti, etichette, tipi e
funzioni in seguito.
Un identificatore deve iniziare con una lettera o con underscore _ seguita
da un numero qualsiasi di lettere, cifre o underscore; viene fatta distinzione tra
lettere maiuscole e lettere minuscole. Benche` il linguaggio non preveda un limite
alla lunghezza massima di un identificatore, e` praticamente impossibile non
imporre un limite al numero di caratteri considerati significativi, per cui ogni
compilatore distingue gli identificatori in base a un certo numero di caratteri
iniziali tralasciando i restanti; il numero di caratteri considerati significativi
varia comunque da sistema a sistema.
Ogni linguaggio si riserva delle parole chiave
(keywords) il cui significato e` prestabilito e che non possono essere utilizzate
dal programmatore come identificatori.
Il C++ non fa eccezione:
asm
continue
float
new
signed
try
auto
default
for
operator
sizeof
typedef
break
delete
friend
private
static
union
case
do
goto
protected
struct
unsigned
catch
double
if
public
switch
virtual
char
else
inline
register
template
void
class
enum
int
return
this
volatile
const
extern
long
short
trow
while
Sono inoltre considerate parole chiave tutte quelle che iniziano con un doppio
underscore __; esse sono riservate per le implementazioni del linguaggio e
per le librerie standard, e il loro uso da parte del programmatore dovrebbe essere
evitato in quanto non sono portabili.
All'interno delle espressioni e` possibile inserire
direttamente dei valori, questi valori sono detti costanti letterali.
La generica costante letterale puo` essere un carattere racchiuso tra apice singolo,
una stringa racchiusa tra doppi apici, un intero o un numero in virgola mobile.
'a' // Costante di tipo carattere
"a" // Stringa di un carattere
"abc" // Ancora una stringa
Un intero puo` essere:
Una sequenza di cifre decimali, eventualmente con segno;
Uno 0 (zero) seguito da un intero in ottale (base 8);
0x o 0X seguito da un intero in esadecimale (base 16);
Nella rappresentazione in esadecimale, oltre alle cifre decimali, e` consentito
l'uso delle lettere da "A" a "F" e da "a" a "f".
Il tipo (Vedi tipi di dato) in cui viene
convertita la costante intera dipende dalla rappresentazione utilizzata e dal
valore:
Base 10: il piu` piccolo atto a contenerla tra int,
long int e unsigned long int
Base 8 o 16: il piu` piccolo atto a contenerla tra int, unsigned int,long int e unsigned long int
Si puo` forzare il tipo da utilizzare aggiungendo alla costante un suffisso
costituito da u o U, e/o l o L: la lettera U
seleziona i tipi unsigned e la L i tipi long;
se solo una tra le due lettere viene specificata, viene scelto il piu` piccolo di
quelli atti a contenere il valore e selezionati dal programmatore:
20 // intero in base 10
024 // 20 in base 8
0x14 // 20 in base 16
12ul // forza unsigned long
12l // forza long
12u // forza unsigned
Un valore in virgola mobile e` costituito da:
Intero decimale, opzionalmente con segno;
Punto decimale
Frazione decimale;
e o E e un intero decimale con segno;
E` possibile ommettere uno tra l'intero decimale e la frazione decimale, ma non
entrambi. E` possibile ommettere uno tra il punto decimale e la lettera E (o e)
e l'intero decimale con segno, ma non entrambi. L'uso della lettera E indica il
ricorso alla notazione scientifica.
Il tipo scelto per rappresentare una costante in virgola mobile e` double, se
non diversamente specificato utilizzando i suffissi F o f per
float, o L o l per long double
Esempi:
.0 // 0 in virgola mobile
110E+4 // equivalente a 110 * 10000 (10 elevato a 4)
.14e-2 // 0.0014
-3.5e+3 // -3500.0
3.5f // forza float
3.4L // forza long double
Alcuni simboli sono utilizzati dal C++ per separare i
vari elementi sintattici o lessicali di un programma o come operatori per costruire
e manipolare espressioni: