Linguaggio C: Programmazione (Variabili)

Abbiamo scritto diverse righe di codice, le abbiamo compilate e quindi abbiamo eseguito il programma risultante per ottenere soltanto una riga di stampa sullo schermo. Ma i programmi non servono soltanto a scrivere qualche frase sullo schermo, se fosse così sarebbe stato più facile e rapido scrivere direttamente la frase risultante sullo schermo. Per poter fare qualcosa di più interessante abbiamo bisogno di introdurre il concetto di variable .

Supponiamo che io vi dica di ricordare il numero 5 nella vostra memoria e poi vi dica di ricordare anche il numero 2. Allora voi avrete registrato due valori nella vostra memoria. Ora, se vi chiedo di sommare 1 dal primo numero voi memorizzerete 6 al posto di 5 come primo numero e quindi ricorderete i due valori 6 (5+1) e 2. A questo punto posso chiedervi di sottrarre i due valori e dirmi il risultato: il valore 4.

Il processo che avete eseguito è simile a quello che il calcolatore può effettuare usando due variabili. In C++ esso viene descritto dalle istruzioni:

a = 5;
b = 2;
a = a + 1;
risultato = a - b;

Naturalmente questo è un esempio molto semplice che coinvolge soltanto due valori interi molto piccoli, ma un calcolatore può memorizzare milioni di valori ed effettuare operazioni matematiche molto complesse su di essi, il tutto ad una velocità inimmaginabile per una persona.

Possiamo quindi definire una variabile come una porzione di memoria in cui memorizzare un valore..

Ogni variabile necessita di un identificatore (un nome) che la distingue da ogni altra variabile, ad esempio nel codice precedente gli identificatori sono a , b e risultato , ma avremmo potuto chiamare le variabili con un qualsiasi altro nome inventato da noi, purchè esso sia un identificatore valido.

Identificatori

Un identificatore valido è una sequenza di una o più lettere, cifre o simboli di sottolineatura ( _ ). La lunghezza di un identificatore non è limitata, ma alcuni compilatori considerano significativi soltanto i primi 32 caratteri (due identificatori con gli stessi primi 32 caratteri denotano la stessa variabile).

Un identificatore non deve contenere spazi o altri caratteri. Sono permessi soltanto lettere, cifre e simboli di sottolineatura. Inoltre, gli identificatori di variabile devono sempre iniziare con una lettera. Essi possono anche iniziare con il simbolo di sottolineatura ( _ ), ma questa possibilità viene di solito riservata per collegamenti esterni. In nessun caso un identificatore può iniziare con una cifra.

Un'altra regola da tener presente quando si scelgono gli identificatori è che essi non devono essere uguali ad una delle parole chiave del linguaggio nè ad una di quelle specifiche del compilatore usato, altrimenti gli identificatori potrebbero essere confusi con tali parole chiave.  Le parole chiave del C++, secondo lo standard ANSI-C++, sono le seguenti:

asm, auto, bool, break, case, catch, char, class, const, const_cast, continue, default, delete, do, double, dynamic_cast, else, enum, explicit, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, operator, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_cast, struct, switch, template, this, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t

Pertanto queste parole non si possono usare come identificatori. Non si possono inoltre usare come identificatori alcuni nomi alternativi di operatori, da usare nel caso in cui la tastiera non contenga i simboli corrispondenti. Tali nomi sono:

and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq

Un compilatore può includere anche qualche altro nome tra le parole riservate. Ad esempio alcuni compilatori che generano codice a 16bit (quali alcuni compilatori per DOS) includono anche le parole far, huge e near tra le parole chiave.

Molto importante: Nel linguaggio C++ le lettere maiuscole sono considerate caratteri diversi dalle corrispondenti lettere minuscole. Quindi, ad esempio, la variabile RISULTATO è diversa sia dalla variabile risultato   che dalla variable Risultato .

Tipi di dato

I valori delle variabili di un programma vengono registrati nella memoria del calcolatore. Il calcolatore deve quindi conoscere quali valori vogliamo memorizzare in una variabile in quanto deve sapere quanta memoria riservare per tali valori. Infatti non tutti i tipi di valore occupano la stessa quantità di memoria. Serve una quantità di memoria diversa per registrare un carattere, un piccolo numero o un grande numero.

La memoria di un calcolatore è suddivisa in byte. Il byte è la più piccola quantità di memoria che possiamo gestire, esso può contenere una relativamente piccola quantità di dati: di norma un singolo carattere o un intero fra 0 e 255. Ma il calcolatore può elaborare anche tipi di dato più complessi che occupano più di un byte. Ecco un elenco dei tipi fondamentali del C++ con l'indicazione della quantità di memoria necessaria e del rango di valori che si possono rappresentare:

TIPI DI DATO ELEMENTARI

NomeByte*DescrizioneRango*
char1carattere o intero di 8 bit.signed: -128 ... 127 
unsigned: 0 ... 255
short2intero di 16 bit.signed: -32768 ... 32767 
unsigned: 0 ... 65535
long4intero di 32 bit.signed:-2147483648 ... 2147483647 
unsigned: 0 ... 4294967295
int*Intero. La sua lunghezza dipende dalla lunghezza del tipo word usato dal sistema operativo. Ad esempio, in MSDOS è di 16 bit mentre in sistemi a 32 bit (quali Windows 9x/2000/NT) è di 32 bit (4 bytes).See shortlong
float4numero in virgola mobile.3.4e + / - 38 (7 cifre decimali)
double8numero in virgola mobile in doppia precisione.1.7e + / - 308 (15 cifre decimali)
long double10numero in virgola mobile in doppia precisione estesa.1.2e + / - 4932 (19 cifre decimali)
bool1Valori Booleani. Può assumere uno dei due valori: true o   false
NOTA: è un tipo aggiunto recentemente allo standard ANSI-C++. Non tutti i compilatori lo accettano.
true or false
wchar_t2Carattere esteso. Viene usato per rappresentare tutti i caratteri internazionali. 
NOTA: è un tipo introdotto recentemente nello standard ANSI-C++. Non tutti i compilatori lo accettano. 
caratteri estesi

* I valori nelle colonne Byte e Range possono variare a seconda del sistema. I valori quì riportati sono quelli più comunemente accettati ed usati da quasi tutti i compilatori.

Oltre a questi tipi di dato fondamentali vi sono anche i puntatori ed il tipo void che vedremo in seguito.

Dichiarazione delle variabili

Prima di usare una variabile occorre dichiararla specificando a quale tipo di dato essa appartenga. La sintassi di una dichiarazione di variabile prevede prima il nome del tipo di dato (quale int , short , float ...) seguito dall'identificatore scelto per denotare tale variabile. Ad esempio:

int a;
float numero;

Sono dichiarazioni di variabili corrette. La prima dichiara una variabile di tipo int denotata dall'identificatore a . La seconda dichiara una variabile di tipo float denotata dall'identificatore numero . Una volta dichiarate, le variabili a e numero possono essere usate nel programma all'interno del loro campo di validità (lo scope ).

Se vogliamo dichiarare più di una variabile dello stesso tipo possiamo farlo in una stessa riga indicando una sola volta il tipo e separando gli identificatori con la virgola. Ad esempio:

int a, b, c;

dichiara tre variabili (ab e c ) di tipo int , ed ha esattamente lo stesso significato di:

int a;
int b;
int c;

I tipi di dato interi (charshort , long e int ) possono essere signed o unsigned a seconda del rango di numeri che si vuole considerare. Quindi per specificare un intero possiamo mettere una delle parole chiave signed o unsigned prima del nome del tipo. Ad esempio:

unsigned short NumeroDiFigli;
signed int IlMioSaldoBancario;

Se non si specifica né signed né unsigned viene assunto signed . Quindi nella seconda dichiarazione avremmo potuto scrivere:

int IlMioSaldoBancario;

con lo stesso significato e nel modo più comunemente usato (infatti la parola chiave non viene quasi mai usata).

L'unica eccezione a questa regola è il tipo char che è considerato diverso sia da signed char che da unsigned char.

Infine possiamo usare signed e unsigned come nomi di tipo con lo stesso significato di signed int e unsigned int rispettivamente. Le seguenti due dichiarazioni sono equivalenti:

unsigned AnnoDiNascita;
unsigned int AnnoDiNascita;

Per capire come funziona una dichiarazione in un programma riconsideriamo il codice C++ dell'esempio sul nostro lavoro mentale che abbiamo proposto all'inizio della sezione:

// operazioni con le variabili

#include <iostream.h>

int main ()
{
  // dichiarazione delle variabili:
  int a, b;
  int risultato;

  // elaborazione:
  a = 5;
  b = 2;
  a = a + 1;
  risultato = a - b;

  // stampa del risultato:
  cout << risultato;

  // terminazione del programma:
  return 0;
}
4


 

Inizializzazione delle variabili

Quando dichiariamo una variabile il suo valore è indeterminato (i bit della zona di memoria riservata alla variabile hanno il valore che era stato loro assegnato da qualche precedente programma). Potremmo volere che una variabile abbia un valore particolare fin dal momento in cui viene dichiarata. Per fare questo basta aggiungere alla dichiarazione un simbolo di uguale seguito dal valore desiderato:

tipo identificatore = valore_iniziale ;

Ad esempio se vogliamo dichiarare una variabile a di tipo int con valore iniziale 0 possiamo scrivere:

int a = 0;

Oltre a questo modo di inizializzare variabili (noto come stile C), vi è un altro modo di inizializzare le variabili più consono allo stile C++: racchiudendo il valore iniziale tra parentesi tonde

tipo identificatore(valore_iniziale );

Ad esempio:

int a(0);

Il C++ accetta entrambe le notazioni.

Scope delle variabili

Tutte le variabili che vogliamo usare devono essere preventivamente dichiarate. Una differenza importante tra C e C++ è che in C++ possiamo dichiarare delle variabili in ogni punto del programma, anche tra due istruzioni eseguibili, e non solo all'inizio di un blocco di istruzioni come è richiesto in C.

Resta comunque normalmente preferibile seguire le indicazioni del C per dichiarare le variabili in quanto è comodo, durante la fase di correzione del programma (debugging), avere le dichiarazioni raggruppate assieme: all'inizio di ogni funzione (per le variabili locali) o direttamente nel corpo del programma al di fuori di ogni funzione (variabili globali).

Le variabili globali si possono usare in tutto il programma dal punto in cui sono dichiarate fino alla fine. 

Lo scopo delle variabili locali è invece limitato al blocco in cui sono dichiarate. Se sono dichiarate all'inizio di una funzione (come in main) il loro scopo è l'intero corpo della funzione. Quedto significa che se nell'esempio ci fosse un'altra funzione diversa da main(), le variabili locali dichiarate in main non sarebbero visibili all'interno di tale funzione e viceversa. 

In C++ lo scopo di una variabile locale è limitato alla parte del blocco in cui esse sono dichiarate che segue la dichiarazione stessa (un blocco è un gruppo di istruzioni racchiuse tra parentesi graffe {}
 

Oltre allo scopo locale e globale esiste anche uno scopo esterno (external ) che non solo è visibile in tutto il file che contiene il programma ma è visibile anche in ogni altro file di programma che venga collegato con esso. 

Costanti: Letterali.

Una costante è una qualsiasi espressione che ha un valore prefissato. Esse si possono suddividere in Numeri Interi, Numeri in Virgola Mobile, Caratteri e Stringhe.

Numeri Interi

1776
+707
-273

sono letterali che denotano numeri interi decimali. Per scrivere una costante intera non occorre usare le virgolette (") o qualche altro carattere speciale. Non ci sono dubbi sul fatto che i letterali precedenti denotino delle costanti: quando scriviamo 1776 in un programma intendiamo proprio il valore 1776 e non altri.

Oltre ai numeri in notazione decimale (quella comunemente usata) il C++ accetta anche letterali che denotano numeri interi ottali (base 8) e numeri interi esadecimali (base 16). Per scrivere un numero in notazione ottale basta premettere il carattere 0 (carattere zero) e per scrivere un numero in notazione esadecimale occorre premettere i due caratteri 0x (zero e x). Ad esempio i seguenti letterali sono equivalenti:

75         // decimale
0113       // ottale
0x4b       // esadecimale

Essi denotano lo stesso numero: 75 (settantacinque) espresso rispettivamente come numero in base 10, in base 8 e in base 16.

Nota: le cifre decimali sono le usuali (0,1,2,3,4,5,6,7,8,9), le cifre ottali sono soltanto (0,1,2,3,4,5,6,7) mentre come cifre esadecimali usiamo (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f).

Numeri in virgola mobile
Sono numeri con una parte frazionaria e/o un fattore esponenziale. Sono rappresentati con letterali in cui compare il punto decimale che separa la parte intera dalla parte decimale (noi usiamo la virgola ma nei paesi anglosassoni si usa il punto) e/o un carattere e seguito da un esponente intero (che si legge "per 10 alla X, dove X è l'intero che segue il carattere e").

3.14159    // 3.14159
6.02e23    // 6.02 x 1023
1.6e-19    // 1.6 x 10-19
3.0        // 3.0

sono tutti letterali che rappresentano numeri in virgola mobile.

Caratteri e stringhe
Vi sono anche dei letterali che rappresentano costanti non numeriche:

'z'
'p'
"Salve gente"
"Come state?"

I primi due rappresentano un singolo carattere mentre gli altri due rappresentano stringhe di diversi caratteri. Osserviamo che i letterali che rappresentano singoli caratteri sono racchiusi tra due caratteri apice (' ) mentre i letterali che rappresentano stringhe sono racchiusi tra due caratteri doppio apice ("). Questo è necessario per poter distinguere valori di tipo stringa da valori di tipo carattere (che sono considerati diversi). Inoltre, l'uso degli apici ( ' ) e ( " ) evita di confondere un letterale carattere o stringa da un identificatore o una parola chiave. Infatti in:

x
'x'

x denota la variabile x, mentre 'x' denota la costante di tipo carattere 'x' .

Per rappresentare con un letterale (o all'interno di un letterale stringa) alcuni caratteri speciale si usano notazioni particolari (i codici di escape). Ecco una lista di tali codici di escape (ognuno di essi inizia con il carattere barra rovesciata (\):

 
\na capo riga
\rritorno carrello
\ttabulazione
\vtabulazione verticale
\bbackspace
\fnuova pagina
\aallerta (beep)
\'apice singolo (' )
\"doppio apice (" )
\?punto interrogativo ( ?)
\\barra rovesciata ( \ )

Ad esempio:

'\n'
'\t'
"Sinistra \t Destra"
"uno\ndue\ntre"

     Possiamo inoltre rappresentare ogni carattere del codice ASCII usando  il  suo codice numerico in ottale preceduto da una sbarra rovesciata (\) oppure il suo codice numerico in esadecimale preceduto da  una  sbarra rovesciata e un carattere  x ( \x ). Ad esempio \23 e \37 rappresentano i caratteri ASCII di codice 19 e 31 mentre, usando la notazione   esadecimale, i medesimi due caratteri si denotano con \x13 e \x1f .                                                                                                                                                                                                             

Costanti definite (#define )

Possiamo usare la direttiva #define del preprocessore per dare un nome ad una costante nel seguente modo:

#define identificatore_di_costante

Ovunque useremo l'identificatore, il preprocessore provvederà a sostituirlo con la costante. Ad esempio

#define PI 3.14159265
#define NEWLINE '\n'
#define WIDTH 100

Questo ci evita di dover riscrivere la stessa costante più volte in posti diversi del programma con la possibilità di commettere errori quali scrivere in qualche posto 3.14159365 invece di 3.14159265. Una volta che abbiamo associato un identificatore ad una costante possiamo usare tale identificatore in ogni punto seguente del programma come se esso fosse una costante. Ad esempio:

circonferenza = 2 * PI * r;
cout << NEWLINE;

La direttiva  #define non è una istruzione C++ ma una direttiva per il preprocessore. Essa deve quindi essere scritta in una sua propria riga e non deve essere aggiunto il carattere punto e virgola (;) alla fine.

Costanti dichiarate ( const )

Usando il prefisso const si possono dichiarare delle costanti appartenenti ad un determinato tipo esattamente allo stesso modo in cui si dichiarano le variabili:

const int larghezza = 100;
const char tab = '\t';
const int cap =  12440;

In realtà le costanti dichiarate sono semplicemente delle variabili il cui valore non può più essere modificato (il compilatore controlla che in nessun punto del programma compaia una assegnazione o una qualsiasi altra istruzione che può modificare il valore di una costante e in tal caso segnala un errore). Naturalmente, siccome una volta create non è più possibile cambiarne il valore, esse devono essere sempre inizializzate con un valore al momento della loro creazione.


Ultime modifiche: lunedì, 9 marzo 2020, 23:04