Concetti Chiave
- In C, gli array e i puntatori sono strettamente correlati, ma presentano anche differenze significative, specialmente nella loro manipolazione e nella semantica delle operazioni aritmetiche.
- Non ci sono controlli sui limiti degli array in C, il che può portare a sovrascritture di memoria, mentre per i puntatori il compilatore emette avvisi in caso di problemi.
- Il nome di un array è considerato un puntatore al primo elemento, permettendo di utilizzare l'indicizzazione come un'espressione aritmetica con puntatori.
- L'operatore sizeof() funziona diversamente: restituisce la dimensione totale per gli array e solo la dimensione del puntatore per i puntatori.
- Non è possibile modificare il contenuto di una stringa letterale tramite un puntatore, ma è consentito farlo se la stringa è assegnata a un array.
Relazione tra array e puntatori
In C c’è una stretta relazione tra gli array e i puntatori, ma anche notevoli differenze. È possibile utilizzare un puntatore usando la notazione array, ma non è possibile usare puntatori come array e viceversa. Le principali difficoltà nel capire le relazioni tra i due tipi di dato sono quelle che riguardano la difficoltà di capire il tipo di oggetto puntato, la semantica delle operazioni aritmetiche eseguibili su puntatori o con puntatori infatti dipende dal tipo di oggetto puntato.
Controlli e conversioni
In C non ci sono controlli sul superamento dei limiti di array, perciò può accadere di sovrascrivere la memoria. Il compilatore in questi casi non dà warning per i puntatori, ma li dà per gli array.
Puntatori a int: int A [10]; int *p = A;
Puntatori ad array di int: int A [10]; int (*p )[10] = &A;
Array di puntatori ad int: int *p [10]
Il compilatore trasforma autonomamente le espressioni con notazione array in espressioni con tipo puntatore:
A → *(A+i)
Ci sono diversi modi per esprime un variabile in un array:
p [1] = *( p +1) = *( A+1) = A [1]) e p[0] = 0 = (1-1) = (x-x)= (&p -&p);
La regola di conversione da notazione array ad espressione aritmetica di tipo puntatore è applicata anche agli array multidimensionali:
A [j] [k] → (*(A+i)) [j] [k] → (*(*(A+i)+j)) [k] → *(*(*(A+i)+j)+k)
di avere righe di diverse lunghezze.
Una dichiarazione di puntatore riserva spazio di memoria per l’oindirizzo dell’oggetto puntato, tranne nel caso in cui l’oggetto puntato sia una stringa letterale, a cui viene riservato spazio di memoria (nel text segment). Non è possibile modificare il contenuto di una stringa letterale se questa è puntata da un puntatore, possiamo però farlo se è utilizzata per inizializzare un array.
Equivalenze e differenze
Equivalenze tra puntatori e array:
- Nome di array è trattato come un puntatore al primo elemento dell’array dal compilatore
- L’indicizzazione di un elemento di un array è uguale a un’espressione aritmetica con tipo puntatore
- Il nome di un array in una dichiarazione di funzione è trattata come un puntatore al primo elemento dell’array
Differenze tra puntatori e array:
- L’operatore sizeof() agisce in modo diverso
- Non è possibile modificare una stringa letterale se assegnata a un puntatore, ma se assegnata ad un array sì
- Non si può assegnare valori ad una variabile di tipo array, ma si può farlo con variabili puntatore
- Differenze legate alla keyword extern
Domande da interrogazione
- Qual è la relazione fondamentale tra array e puntatori in C?
- Quali sono i rischi associati all'uso di array in C?
- Come avviene la conversione tra notazione array e puntatori?
- Quali sono le principali differenze tra puntatori e array?
In C, gli array sono trattati come puntatori al primo elemento, ma non è possibile utilizzare puntatori come array e viceversa. La comprensione di questa relazione è complicata dalla semantica delle operazioni aritmetiche sui puntatori, che dipendono dal tipo di oggetto puntato.
In C, non ci sono controlli sul superamento dei limiti degli array, il che può portare a sovrascrivere la memoria. Il compilatore non fornisce avvisi per i puntatori in questi casi, ma lo fa per gli array.
Il compilatore trasforma automaticamente le espressioni in notazione array in espressioni di tipo puntatore, ad esempio, A è equivalente a *(A+i). Questa regola si applica anche agli array multidimensionali.
Le differenze includono il comportamento dell'operatore sizeof(), la possibilità di modificare stringhe letterali, l'assegnazione di valori e le differenze legate alla keyword extern. Ad esempio, non si possono assegnare valori a variabili di tipo array, ma è possibile farlo con variabili puntatore.