Guida Linguaggio C: Le Costanti, i Tipi, le Variabili | |||||||
18 Novembre 2007 | C |
![]() ![]() ![]() |
|
|
![]() |
Introduzione
Un identificatore è un nome che viene associato a diverse entità come costanti, tipi, variabili, funzioni, ecc. e serve ad identificare la particolare entità. L'identificatore sarà poi sostituito dall'indirizzo della variabile o della costante o della funzione.Gli identificatori in C devono soddisfare determinati vincoli. Un identificatore deve iniziare con un carattere o con il simbolo '_' (underline), e può contenere solo lettere, numeri e il simbolo underline.
Esempio
int a, _a, a2; // identificatore corretto
char 2b; //identificatore non corretto
Le Costanti
Una costante è un identificatore a cui è associato un valore che resterà fisso per tutta la durata dell'esecuzione del programma. A differenza di una variabile, il cui valore può variare più volte durante l'esecuzione del programma la costante mantiene inalterato il suo valore.Vi sono due modi per dichiarare una costante: utilizzare la const o utilizzare la direttiva al preprocessore define. Nel primo caso si associa all'identificatore il valore, la costante viene vista come una variabile con un valore fisso, nel secondo caso il compilatore andrà a sostituire, in fase di compilazione, a tutte le occorrenze dell'identificatore il valore associato.
In sostanza, definendo una costante tramite la const il compilatore farà sì (inserirà del codice) che in fase di esecuzione vi sarà una locazione di memoria relativa alla costante in cui sarà presente il valore associato alla costante. Definendo una costante tramite la define il compilatore sostituirà a tutte le occorrenze dell'identificatore il valore associato, in questo modo non vi sarà alcuna locazione di memoria associata alla costante ed il valore sarà inserito direttamente all'interno del codice.
La definizione di costante, tramite la const, avrà la seguente forma
const tipo id = valore;
dopo la parola chiave const si indicherà il tipo della costante, l'identificatore e quindi il valore.
Esempio
Alcuni esempi di dichiarazioni di costanti sono le seguenti
Le prime due dichiarazioni di costanti sono banali dichiarazioni di un intero e di un carattere. Da notare come un carattere viene indicato tra apice singolo ('a').
Particolarmente interessante è vedere come viene dichiarato un array di caratteri. In C il tipo stringa non esiste, a differenza del C++, quindi le stringhe vengono gestite tramite gli array di caratteri.
Una costante stringa può essere dichiarata in due modi, come indicato in riga 4, indicando la stringa per esteso racchiusa tra doppi apici, oppure come in riga 5, carattere per carattere ciascuno racchiuso tra apici singolo. Nel primo caso il compilatore di assegnare correttamente il valore alla costante.
Da notare inoltre che in quelle dichiarazioni non si è inserita la dimensione dell'array. Non è necessario, sarà sempre il compilatore a sistemare le cose.
Un array di costanti può essere dichiarato in due modi, specificando, come in riga 8, o non specificando, come in riga 7, la dimensione dell'array. Tutti gli elementi dell'array sono racchiusi tra parentesi graffe e ciascun elemento è separato da una virgola.
Tutti gli elementi non specificati nella definizione di array di costanti intere, come in riga 9, sono automaticamente fissati a 0. Nell'esempio in riga 9 l'array e3 sarà costituito dai seguenti elementi: 1 e 2, specificati, e 0, non specificato.
Una matrice di costanti può essere dichiarata specificando, come in riga 11, o non specificando, come in riga 10, la dimensione dell'array esterno. Tutti gli elementi dell'array sono racchiusi tra parentesi graffe e ciascun elemento è separato da una virgola. In questo caso ciascun elemento è a sua volta un array, quindi l'elemento sarà costituito da elementi racchiusi tra parentesi graffe e separati dalle virgole.
Un numero intero può essere espresso in decimale, binario, ottale ed esadecimale. Un numero con lo 0 come prima cifra è interpretato come un numero espresso in base ottale, un numero con il prefisso "0x" o "0X" è interpretato come un numero espresso in base esadecimale, un numero con
Un costante reale può essere definita in due modi, usando solo la parte intera e la parte frazionaria, come in riga 18, o usando la notazione esponenziale, come in riga 19.
const int a = 1;
const char b = 'a';
const char c[] = "Stringa";
const char d[] = {'S', 't', 'r', 'i', 'n', 'g', 'a'};
const int e[] = {1, 2, 3};
const int e2[3] = {1, 2, 3};
const int e3[3] = {1, 2};
const int f[][2] = {{1, 2}, {3, 4}, {5, 6}};
const int f2[3][2] = {{1, 2}, {3, 4}, {5, 6}};
const int g = 23; //numero 23 in decimale
const int h = 027; //numero 23 in ottale
const int i = 0x17; //numero 23 in esadecimale
const float k = 23.47;
const float l = 2.347e1;
Le prime due dichiarazioni di costanti sono banali dichiarazioni di un intero e di un carattere. Da notare come un carattere viene indicato tra apice singolo ('a').
Particolarmente interessante è vedere come viene dichiarato un array di caratteri. In C il tipo stringa non esiste, a differenza del C++, quindi le stringhe vengono gestite tramite gli array di caratteri.
Una costante stringa può essere dichiarata in due modi, come indicato in riga 4, indicando la stringa per esteso racchiusa tra doppi apici, oppure come in riga 5, carattere per carattere ciascuno racchiuso tra apici singolo. Nel primo caso il compilatore di assegnare correttamente il valore alla costante.
Da notare inoltre che in quelle dichiarazioni non si è inserita la dimensione dell'array. Non è necessario, sarà sempre il compilatore a sistemare le cose.
Un array di costanti può essere dichiarato in due modi, specificando, come in riga 8, o non specificando, come in riga 7, la dimensione dell'array. Tutti gli elementi dell'array sono racchiusi tra parentesi graffe e ciascun elemento è separato da una virgola.
Tutti gli elementi non specificati nella definizione di array di costanti intere, come in riga 9, sono automaticamente fissati a 0. Nell'esempio in riga 9 l'array e3 sarà costituito dai seguenti elementi: 1 e 2, specificati, e 0, non specificato.
Una matrice di costanti può essere dichiarata specificando, come in riga 11, o non specificando, come in riga 10, la dimensione dell'array esterno. Tutti gli elementi dell'array sono racchiusi tra parentesi graffe e ciascun elemento è separato da una virgola. In questo caso ciascun elemento è a sua volta un array, quindi l'elemento sarà costituito da elementi racchiusi tra parentesi graffe e separati dalle virgole.
Un numero intero può essere espresso in decimale, binario, ottale ed esadecimale. Un numero con lo 0 come prima cifra è interpretato come un numero espresso in base ottale, un numero con il prefisso "0x" o "0X" è interpretato come un numero espresso in base esadecimale, un numero con
Un costante reale può essere definita in due modi, usando solo la parte intera e la parte frazionaria, come in riga 18, o usando la notazione esponenziale, come in riga 19.
La definizione di costante, tramite la define, avrà la seguente forma
#define id valore
dopo la direttiva define si indicherà l'identificatore della costante e quindi il valore.
Esempio
#define a 12
I Tipi Predefiniti
In C i tipi predefiniti sono descritti nella tabella che segue, il range dei tipi numerici è definito dalle macro definite nel file limits.h e nel file float.h.Tipo | Descrizione | |
---|---|---|
Intero | unsigned short int |
Può rappresentare un numero intero compreso tra 0 e il valore della macro
USHRT_MAX definita in
limits.h.
In genere USHRT_MAX=65535 e variabili di questo tipo occupano 2 byte. |
Intero | unsigned int |
Può rappresentare un numero intero compreso tra 0 ed il valore della macro
UINT_MAX definita in
limits.h.
Il valore di UINT_MAX può variare da una macchina all'altra. Può avere la stessa dimensione di uno short int su una macchina e la stessa dimensione di un long int su un'altra macchina. In genere può essere UINT_MAX=65535, o UINT_MAX=4294967295. |
Intero | unsigned long int |
Può rappresentare un numero intero compreso tra 0 ed il valore della macro
ULONG_MAX definita in
limits.h.
In genere può essere ULONG_MAX=4294967295. |
Intero | signed short int ovvero short int |
Può rappresentare un numero intero compreso tra i valori delle macro
SHRT_MIN e
SHRT_MAX
definite in limits.h.
In genere SHRT_MIN=-32768, SHRT_MAX=32767, e variabili di questo tipo occupano 2 byte. |
Intero | signed int ovvero int |
Può rappresentare un numero intero compreso tra i valori delle macro
INT_MIN e
INT_MAX
definite in limits.h.
Il valore di INT_MIN e INT_MAX può variare da una macchina all'altra. Può avere la stessa dimensione di uno short int su una macchina e la stessa dimensione di un long int su un'altra macchina. In genere può essere INT_MIN=-32768 e INT_MAX=32767, o INT_MIN=-2147483648 e INT_MAX=2147483647. |
Intero | signed long int ovvero long int |
Può rappresentare un numero intero compreso tra i valori delle macro
LONG_MIN e
LONG_MAX
definite in limits.h.
In genere LONG_MIN=-2147483648, LONG_MAX=2147483647, e variabili di questo tipo occupano 4 byte. |
Carattere | unsigned char |
Può rappresentare un carattere il cui codice è tra 0 ed il valore della macro
UCHAR_MAX definita in
limits.h.
In genere può essere UCHAR_MAX=255, e variabili di questo tipo occupano 1 byte. |
Carattere | signed char ovvero char |
Può rappresentare un carattere il cui codice è tra i valori delle macro
SCHAR_MIN e
SCHAR_MAX
definite in limits.h.
In genere SCHAR_MIN=-128, SCHAR_MAX=127, e variabili di questo tipo occupano 1 byte. |
Reale | float | Può rappresentare un numero reale in singola precisione compreso tra i valori delle macro FLT_MIN e FLT_MAX definite in float.h. In genere FLT_MIN=-1038, FLT_MAX=1038, e le variabili di questo tipo occupano 4 byte. |
Reale | double | Può rappresentare un numero reale in doppia precisione compreso tra i valori delle macro DBL_MIN e DBL_MAX definite in float.h. In genere DBL_MIN=-10308, DBL_MAX=10308, e le variabili di questo tipo occupano 6 byte. |
Reale | long double | Può rappresentare un numero reale in doppia precisione compreso tra i valori delle macro LDBL_MIN e LDBL_MAX definite in float.h. In genere LDBL_MIN=-104932, LDBL_MAX=104932, e le variabili di questo tipo occupano 8 byte. |
void | Tipo vuoto. |
Esempio
Il tipo void può essere usato in diversi contesti.
Può essere usato nella defizione di una funzione per indicare che la funzione
non restituirà alcun valore
o per indicare che la funzione non accetta argomenti
Si può comunque anche omettere il void, la definizione seguente è uguale alla precedente
Si può usare per dichiarare un puntatore generico
void func()
{
...
}
o per indicare che la funzione non accetta argomenti
int func(void)
{
...
}
Si può comunque anche omettere il void, la definizione seguente è uguale alla precedente
int func()
{
...
}
Si può usare per dichiarare un puntatore generico
void *p;
Tramite la enum è poi possibile definire un tipo di dato enumerativo elencando i valori assumibili da quel tipo di dato. Una variabile di tipo enumerativo può assumere solo i valori appartenenti a questa lista.
Esempio
enum giorno {domenica, lunedi, martedi, mercoledi, giovedi, venerdi, sabato};
enum paese {Italia, Francia, Spagna, Germania, Svizzera=10, Inghilterra, Cina};
Nel primo caso viene definito il tipo giorno elencando i valori simbolici che può assumere una variabile di questo tipo. Ad ogni valore simbolico sarà associato un numero intero. Al primo valore simbolico verrà associato il numero 0, al valore simbolico successivo il numero 1, e così via.
Ad un valore simbolico il programmatore può far corrispondere un preciso numero. Nel secondo caso al valore simbolico 'Svizzera' viene fatto corrispondere il numero 10. Il valore simbolico successivo avrà associato il numero 11.
Un tipo di dato enumerativo non può presentare un valore simbolico già presente nella dichiarazione di un altro tipo enumerativo.
enum colori1 {giallo, verde, rosso, marrone, blu};
enum colori2 {arancione, grigio, verde, bianco, ciano, magenta};
Nel frammento di codice precedente il valore simbolico verde è presente sia nella dichiarazione di colori1 che in quella di colori2. Questo frammento di codice genererà un errore in fase di compilazione.
I Tipi Strutturati
Array
Un array è una collezione di dati dello stesso tipo. È una struttura costituita da un numero definito di elementi tutti dello stesso tipo.
Figura 1.
Gli elementi di un array possono anche essere a loro volta degli array. In questo caso ogni cella dell'array conterrà un array. Che a sua volta potrebbe avere come elementi degli array, e così via. Un array di questo tipo viene chiamato array multidimensionale.
Nel caso in cui gli elementi di un array siano degli array monodimensionali l'array viene invece chiamato array bidimensionale o matrice.
Esempio
typedef
{
char cognome[30], nome[30];
int eta;
} persona;
persona persone[100];
int a[10];
int b[] = {0, 1, 2, 3, 4};
int matrice[10][5];
int multidim[10][10][5];
È possibile definire array di strutture, come nel primo caso, così come array di tipi semplici come interi, caratteri, ecc. Si possono definire subito, al momento della dichiarazione, gli elementi dell'array.
È anche possibile definire matrici, o array multimensionali.
Union
Una union è una collezione di elementi, che possono anche essere di tipo diverso, in cui tutti gli elementi condividono la stessa area di memoria. Questo significa che tutti gli elementi di una union saranno memorizzati nella stessa area di memoria, ed è quindi possibile utilizzare un solo elemento alla volta. Una union può contenere elementi di qualsiasi tipo, quindi la dimensione della union è pari alla dimensione del più grande dei suoi elementi.Una dichiarazione di union ha la seguente forma
union
{
tipo-elemento elemento1;
tipo-elemento elemento2;
...
tipo-elemento elementon;
} nome-union;
Esempio
union
{
char cognomenome[50];
int codice;
} persona;
La union persona individua una persona, con nome e cognome o tramite un codice. La dimensione della union è pari alla dimensione del suo elemento più grande. In questo caso la dimensione della union persona è pari alla dimensione dell'array cognomenome.
Strutture
Una struttura è una collezione di elementi, detti membri, anche di tipo diverso. I membri della struttura sono memorizzati in modo sequenziale nell'area di memoria dedicata alla struttura. A differenza della union, quindi, i membri della struttura non condividono la stessa area di memoria. Una dichiarazione di struttura ha la seguente formastruct
{
tipo-elemento elemento1;
tipo-elemento elemento2;
...
tipo-elemento elementon;
} nome-struct;
Esempio
struct
{
char cognome[30], nome[30];
int eta;
} persona;
Le Parole Chiave
Per il C sono definite le seguenti parole chiave:auto | const | do | extern | if | return | static | union | while |
break | continue | double | float | int | short | struct | unsigned | |
case | defined | else | for | long | signed | switch | void | |
char | defined | enum | goto | register | sizeof | typedef | volatile |
Guida Linguaggio C
- Introduzione
- Direttive
- Costanti, Tipi, Variabili
- Operatori
- L'input
- L'Output
- Controlli
- Funzioni
- Array
- Puntatori
- Stringhe
- I File
- L'Input da File
- L'Output su File