Capitolo precedente. | Indice del capitolo. | Indice analitico globale. | Capitolo successivo. |
Capitolo 5
Puntatori, vettori, stringhe
Un puntatore è una variabile predisposta per contenere un indirizzo di memoria. Attraverso i puntatori diventa possibile manipolare gli indirizzi di memoria. Si tenga presente che ogni variabile occupa uno spazio di memoria, e che quindi è possibile ottenerne l'indirizzo di memoria.
Una variabile di tipo puntatore si dichiara specificando il tipo di dato a cui si punta ed il carattere *.
La dichiarazione
I valori di pint sono tutti numeri interi positivi, compreso il numero 0, che saranno interpretati come indirizzi di memoria. La costante 0 viene in genere utilizzata per inizializzare variabili di tipo puntatore.
Alcuni esempi di assegnazione per variabili di tipo puntatore sono
&5; | non si può far riferimento all'indirizzo di una costante |
int v[10]; | |
&v; | v è una costante che indica l'indirizzo del vettore |
&(i+3); | non si può fare riferimento ad una espressione |
mentre se v è un vettore allora |
|
&v[3], &v[i+2]; | sono tutte espressioni corrette. |
Esempio.
int x = 4, y = 5, z[20]; | int *ip; | /* ip è un puntatore a intero */ |
ip = &x; | /* ip punta a x */ | |
y = *ip; | y = 4 | |
*ip = 0; | x = 0 | |
ip = &z[0]; | ip punta a z[0] |
Se ip punta ad un intero x allora *ip può essere utilizzato ovunque è possibile utilizzare x. Ad esempio
*ip = *ip +10; | incrementa *ip di 10. |
y = *ip + 1; | incrementa di 1 la variabile a cui punta ip e l'assegna a y |
*ip += 1; | incrementa ciò a cui punta ip di 1 |
++*ip; | incrementa ciò a cui punta ip di 1 |
(*ip)++; | incrementa ciò a cui punta ip di 1 |
*ip++; | incrementa l'indirizzo di ip di 1 e poi ne considera il contenuto |
5.2 I puntatori come parametri in una function.
Nei capitoli precedenti abbiamo visto come il passaggio dei parametri per una funzione avvenga per valore. Questo significa che le eventuali modifiche effettuate nella function non alterano i valori originali. Ora con i puntatori è possibile realizzare la chiamata di una funzione passando i parametri per indirizzo: è sufficiente dichiarare i parametri della funzione di tipo puntatore. Ad esempio
effettua lo scambio di a e b solo localmente, non modificando i dati originali.
Mentre con
la chiamata
5.3 Relazione tra puntatori e vettori.
In molti casi puntatori e vettori sono utilizzati indifferentemente per accedere alla memoria. La differenza sostanziale tra i due è che un puntatore è una variabile predisposta per contenere un indirizzo, il nome di un vettore è un indirizzo.
Supponiamo di avere la seguente dichiarazione:
p=v; | p=&v[0]; | sono equivalenti |
p=v+1; | p=&v[1]; | sono equivalenti |
Esercizio: Siano
5.4 Aritmetica dei puntatori.
È questa una delle caratteristiche più potenti e più pericolose del C: la possibilità di operare sugli indirizzi di memoria con operazioni aritmetiche. Sia p una variabile di tipo puntatore ad un particolare tipo t. Con
In Ansi C esiste anche il puntatore generico, dichiarato
Nella dichiarazione di function che operano su vettori è possibile utilizzare indifferentemente la simbologia con gli indici o le variabili puntatore. Ad esempio è possibile scrivere:
5.5 cast.
L'operatore di cast permette di forzare particolari conversioni di espressioni. La sintassi è la seguente:
Ad esempio sia
Ad esempio l'espressione
Una operazione di cast equivale ad assegnare il risultato dell'espressione ad una variabile del tipo specificato dal cast ed utilizzarne il risultato.
L'operatore di cast, unario, è molto utile quando si opera con i puntatori, per modificare il tipo delle variabili di tipo puntatore.
Sia
5.7 Operazioni sulle stringhe.
Le funzioni che operano sulle stringhe, cioè su vettori di caratteri terminati da \0, permettono di confrontare, copiare, ricercare stringhe e caratteri, e permettono tante altre operazioni.
char *strchr( const char *string, int c )
Dove
string | Stringa sorgente |
c | Carattere da ricercare |
La funzione restituisce un puntatore alla prima occorrenza di c, convertito in un carattere, in string. Il carattere c può essere il carattere \0, poichè il carattere nullo può essere inserito nella ricerca. La funzione restituisce NULL se il carattere non è trovato. La funzione opera su stringhe terminate dal carattere \0.
int strcmp( const char *string1, const char *string2 );
Dove
string1, string2 | sono le stringhe da confrontare |
La funzione strcmp confronta le due stringhe in base al
codice ashii e restituisce un intero secondo le seguenti condizioni:
< | string1 minore di string2 |
0 | string1 uguale a string2 |
> | string1 più grande di string2 |
char *strcpy( char *string1, const char *string2 );
Dove
string1 | Stringa di destinazione |
string2 | Stringa sorgente |
La funzione strcpy copia string2, incluso il carattere terminatore, nella posizione indicata da string1 e ritorna string1. Opera su stringa contenente il carattere terminatore. Non effettua nessun controllo di overflow su string1.
size_t strlen( const char *string );
Dove
string è una stringa terminata da \0.
Restituisce la lunghezza in byte di string, non calcolando il carattere \0.
char *strncat( char *string1, const char *string2, size_t count );
Dove
string1 | Stringa di destinazione |
string2 | Stringa sorgente |
count | Numero di carattere da aggiungere |
La funzione strncat aggiunge al massimo count caratteri di string2 in fondo a string1, terminandoli con \0 e restituisce string1. Se count è maggiore della lunghezza di string2 vengono aggiunti solo i caratteri di string2.
int strncmp( const char *string1, const char *string2, size_t count );
Dove
string1, string2 | Stringhe da confrontare |
count | Numero di caratteri da confrontare |
La funzione strncmp confronta alfabeticamente al massimo i primi count caratteri di string1 e string2 e restituisce un intero con il seguente significato:
< | string1 minore di string2 |
0 | string1 uguale a string2 |
> | string1 più grande di string2 |
char *strncpy( char *string1, const char *string2, size_t count );
Dove
string1 | Stringa di destinazione |
string2 | Stringa sorgente |
count | Numero di caratteri da copiare |
La funzione strncpy copia count caratteri da string2 a string1. Se count è maggiore della lunghezza di string1 allora sono copiati solo i caratteri di string2 ma il carattere \0 non viene aggiunto in fondo a string1, mentre se count è minore della lunghezza di string2 allora viene aggiunto il carattere \0 alla fine in string1. Potrebbero sorgere problemi se le stringhe si sovrappongono parzialmente. Viene restituito string1.
char *strpbrk( const char *string1, const char *string2 );
Dove
string1 | Stringa sorgente |
string2 | Insieme di caratteri |
La funzione strpbrk ricerca in string1 la prima occorrenza di un qualsiasi carattere di string2. Il carattere \0 non viene ricercato. La funzione restituisce NULL se le due stringhe non hanno alcun carattere in comune.
char *strstr( const char *string1, const char *string2 );
Dove
string1 | Stringa dove ricercare |
string2 | Stringa da ricercare |
La funzione strstr restituisce un puntatore alla rpima occorrenza di string2 in string1. Restituisce NULL se string2 non è contenuta in string1.
char *strtok( char *string1, const char *string2 );
Dove
string1 | Stringa contenente i token |
string2 | Caratteri di delimitazione dei token |
La funzione strtok considera string1 come una sequenza di 0 o più token, mentre string2 come un insieme di caratteri che servono per delimitare un token dal successivo. I token di string1 possono essere estratti con una serie di chiamate alla funzione strtok. Dopo la prima chiamata strtok ricerca in string1 la prima sequenza di caratteri indicata da string2, scartando i delimitatori e restituendo il puntatore al primo token. Per ottenere gli altri token basta richiamare la funzione, passando come string1 la stringa nulla. È importante notare che le chiamate a questa funzione modificano string1 perchè viene inserito il carattere \0 al posto del delimitatore. Quando non ci sono più token viene restituito NULL.
char *strcat( char *string1, const char *string2 );
Dove
string1 | Stringa di destinazione |
string2 | Stringa sorgente |
La funzione strcat aggiunge alla string1 la string2. Entrambe le stringhe devono essere terminate da \0. La funzione restituisce il puntatore alla stringa concatenata, cioè a string1. Non viene effettuato alcun controllo di overflow.
char *strrchr( const char *string, int c );
Dove
string | Stringa utilizzata per la ricerca |
c | Carattere da ricercare |
La funzione strrchr ricerca l'ultima occorrenza di c, convertito in carattere, in string. String è una stringa terminata da \0, che può essere incluso nella ricerca. La funzione restituisce un puntatore all'ultima occorrenza di c in string. NULL se il carattere non è stato trovato.
size_t strspn( const char *string1, const char *string2 );
Dove
string1 | Stringa su cui effettuare la ricerca |
string2 | Insieme di caratteri. |
La funzione strspn restituisce l'indice del primo carattere di string1 che non appartiene a string2. Questo valore equivale alla lunghezza della sottostringa iniziale contenente alcuni caratteri di string2. Se il primo carattere di string1 non appartiene a string2 la funzione restituisce 0.
size_t strcspn( const char *string1, const char *string2 );
Dove
string1 | Stinga utilizzata per la ricerca |
string2 | Insieme di caratteri |