Tipi di dati elementari Il C (e il C++) è un linguaggio cosiddetto “tipato”, ovvero: + di ogni variabile deve essere dichiarato il tipo di appartenenza; + il tipo di una variabile stabilisce il modo con cui essa viene codificata dal calcolatore e determina le operazioni che possono essere effettuate su e con quella variabile; + il controllo sui tipi è molto forte: l'interazione fra variabili di tipo diverso e la conversione da un tipo all'altro (casting) è esplicitamente regolato e limitato
Tipi di dati elementari int numero intero 4 byte char codice ascii di un carattere 1 byte (interpretabile anche come numero intero non negativo) float numero in virgola mobile (6-7 cifre significative) 4 byte double numero in virgola mobile (15-16 cifre significative) 8 byte bool valore “logico”: vero (true) o falso (false) 1 byte I tipi possibili sono in realtà molti di più: + ogni tipo nativo può essere specializzato mediante i qualificatori di tipo + il programma stesso può creare propri tipi personalizzati (detti "tipi astratti")
Dichiarazione e definizione degli identificatori Un identificatore è un nome simbolico che il programmatore assegna a un'entità del linguaggio (variabili, funzioni...): una volta effettuata l’assegnazione, il compilatore sarà in grado di identificare quell'entità (individuarla e riconoscerne il tipo) ogni volta che incontra il nome che le è stato assegnato. Il programmatore può eleggere a identificatore una qualsiasi sequenza di lettere (maiuscole o minuscole) e di cifre numeriche che inizi con una lettera e senza caratteri di altro tipo o spazi bianchi. E… ...e che non sia una parola-chiave (keyword) già usata dal C/C++ auto bool break case catch char class const const_class continue default delete do double dynamic_cast else enum explicit extern false float for friend goto if inline int long main mutable namespace new operator private protected public register reinterpret_class return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename union unsigned using virtual void volatile wmain while
Dichiarazione e definizione degli identificatori + In C++ tutti gli identificatori devono essere dichiarati prima di essere utilizzati (non necessariamente all'inizio del programma). + Per le variabili, la dichiarazione coincide con la specificazione del tipo; la sintassi è proprio l’elencazione degli identificativi preceduta dal tipo desiderato. Ad esempio: int Variabile_Intera; int ore, giorni, mesi; + Ogni dichiarazione viene interpretata come un’istruzione, e quindi pretende il “;” per separarla dalla successiva.
Qualificatori e specificatori di tipo Un qualificatore di tipo è una keyword che, in una istruzione di dichiarazione, si premette a un tipo elementare per “qualificare ulteriormente” il tipo che si sta dichiarando. Esistono 4 qualificatori: short, long, signed, unsigned. (Se il tipo è omesso, è sottointeso int) I qualificatori short e long si applicano al tipo int. Essi stabiliscono la dimensione della memoria occupata dalle rispettive variabili di appartenenza. I qualificatori signed e unsigned si applicano ai tipi “interi” int e char. Essi determinano se le rispettive variabili di appartenenza possono assumere o meno valori negativi. (Non è possibile dare delle regole generali perché il particolare risultato che si ha usando questi qualificatori dipende dalla piattaforma utilizzata.)
Qualificatori e specificatori di tipo Uno specificatore è una keyword che, in una istruzione di dichiarazione, si premette a un tipo (elementare o non) e all'eventuale qualificatore, per definire ulteriori caratteristiche sul trattamento dell'entità dichiarata. Esistono svariati tipi di specificatori, con funzioni diverse: li introdurremo via via durante il corso, quando sarà necessario, per ora ne vediamo subito solo due: const e, per ora solo a mo’ di esempio, extern.
Qualificatori e specificatori di tipo Lo specificatore const, indica al compilatore che il contenuto della variabile non può più essere modificato (e, ovviamente, una variabile definita const deve sempre essere inizializzata...). Esempio: const double pigreco = 3.14159265385; L'uso di const è fortemente consigliato rispetto all'alternativa di scrivere più volte la stessa costante nelle istruzioni del programma; infatti se il programmatore decide di cambiarne il valore, e ha usato const, è sufficiente che modifichi la sola istruzione di definizione. In linguaggio informatico, si usa il termine “costanti” tipicamente proprio per riferirsi a "variabili definite const“, distinguendole dalle costanti “esplicite" che sono chiamate “costanti letterali” (dall’inglese “literals”).
Qualificatori e specificatori di tipo Lo specificatore extern, indica al compilatore (più propriamente al linker) che la variabile che segue è definita in un altro file del programma (e quindi l'istruzione serve solo ad identificare il tipo della variabile e a permetterne l'utilizzo); Esempio: extern int error_number; In questo caso, la dichiarazione si limita ad informare il compilatore del C++ che un certo identificatore appartiene a un certo tipo, ma non viene considerata in fase di esecuzione del programma. Le dichiarazioni viste finora, invece, comportano anche un'operazione eseguibile: l’allocazione di un'apposita area di memoria; queste (tipiche) dichiarazioni sono dette definizioni. (vedremo in seguito il contesto tipico per l’uso di variabili extern…)
Literals Per le variabili (e le costanti), dunque, la specificazione esplicita del tipo stabilisce il modo con cui essa viene codificata e le operazioni che possono essere effettuate con e su di essa. Per le espressioni letterali, invece, il tipo corrispondente viene “dedotto” dal modo in cui l’espressione viene scritta nel codice.
Literals Costanti intere + Un numero senza prefissi o suffissi viene interpretato in base decimale e trattato come una costante di tipo int (o unsigned int se la costante specificata è maggiore del massimo numero positivo signed int); + Un numero con prefisso 0 (zero) è interpretato in base ottale e trattato come int (o unsigned int); + Un numero con prefisso 0x o 0X è interpretato in base esadecimale e trattato come int (o unsigned int). Le "cifre" a,b,c,d,e,f possono essere scritte sia in maiuscolo che in minuscolo; + In qualunque caso, la presenza del suffisso L indica che il numero deve essere di tipo long int, mentre la presenza del suffisso U indica che il numero deve essere di tipo unsigned int.
Costanti in virgola mobile Literals Costanti in virgola mobile Una costante in virgola mobile è sempre indicata in base 10 e può essere specificato in 2 modi: + parte_intera.parte_decimale (il punto è obbligatorio) + notazione esponenziale (il punto non è obbligatorio) Esempi: 15.75 -1.5e2 25E-4 10. In entrambe le notazioni, se il numero è scritto senza suffissi, è assunto di tipo double. Per forzare il tipo float bisogna apporre il suffisso f (o F). Esempi: 10.3 //tipo double 1.4e-5f //è di tipo float
Literals Costanti carattere Una costante carattere è rappresentata inserendo fra singoli apici un carattere stampabile oppure una sequenza di escape. Esempi: 'A' //carattere A '\n' //carattere newline '\003' //carattere cuoricino In memoria un carattere è rappresentato da un numero intero di 1 byte (il suo codice ascii). Il carattere NULL ha codice ascii 0 e si rappresenta con '\0' (da non confondere con il carattere 0 decimale che ha codice ascii 48).
Literals Costanti stringa Una costante stringa è rappresentata inserendo un insieme di caratteri (fra cui anche sequenze di escape) fra doppi apici (virgolette). Esempio: "Ciao a tutti!\n" In C++ (come in C) non esistono le stringhe come tipo intrinseco. Infatti esse sono definite come sequenze (array) di caratteri, con una differenza rispetto ai normali array: il compilatore, nel creare una costante stringa, aggiunge automaticamente un NULL dopo l'ultimo carattere (si dice che le stringhe sono "array di caratteri null terminated"). E quindi, per esempio, 'A' e "A" sono due costanti diverse : 'A‘ //carattere e occupa 1 byte (con il numero 65) "A" //è una stringa e occupa 2 byte (con i numeri 65 e 0)
Definizione con inizializzazione La struttura tipica di una dichiarazione, per riassumere, è la seguente: [specificatore] [qualificatore] tipo identificatore1; in cui le parti fra quadre sono opzionali. Di fatto esiste un’ulteriore parte opzionale che può essere usata nel caso di una definizione, e consiste nell’inizializzazione della variabile dichiarata: [specificatore] [qualificatore] tipo identificatore1 [= valore]; Esempio: unsigned int spese= 45; int ricavi = 23; int guadagno = ricavi – spese;