Storia della questione:
L'aritmetica dei puntatori è emersa nel linguaggio C per garantire un'efficiente gestione della memoria, degli array e delle strutture. È strettamente legata all'indirizzamento della memoria e a come C opera a livello più basso: sommare o sottrarre da un puntatore consente di accedere agli elementi sequenziali di un array.
Problema:
La principale difficoltà sta nel fatto che l'aritmetica dei puntatori non è equivalente all'aritmetica dei numeri: sommare 1 a un puntatore aumenta il suo valore della dimensione del tipo a cui punta. Errori classici includono l'uscita dai limiti dell'array allocato, lavorare con puntatori di tipi incompatibili e tentare calcoli con void *.
Soluzione:
Tenere sempre conto della dimensione del tipo quando si lavora con i puntatori, evitare calcoli algebrici con void*, controllare i confini dell'array. Per accedere agli elementi di un array, usare l'indicizzazione o puntatori calcolati, verificando preventivamente i confini.
Esempio di codice:
#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; printf("%d\n", *(p + 2)); // 3 // Non valido: p + 10 esce dai confini dell'array return 0; }
Caratteristiche chiave:
È possibile sommare a un puntatore un valore di tipo float o variabili di altri tipi?
No, ai puntatori è possibile sommare o sottrarre solo valori di tipo intero. Usare una virgola mobile porterà a un errore di compilazione.
*Restituisce (arr + i) e arr[i] sempre lo stesso valore, anche se i esce dai confini dell'array?
No. Semanticamente sono equivalenti, ma se l'indice esce dai limiti dell'array, entrambe le espressioni portano a un comportamento indefinito (undefined behavior).
Cosa succede sottraendo puntatori che fanno riferimento a array diversi?
Il risultato non è definito dallo standard ed è considerato un errore. È possibile sottrarre solo puntatori che si trovano all'interno dello stesso array (o della memoria allocata in un unico blocco).
buffer overrun)Nel codice, uno sviluppatore utilizza l'aritmetica dei puntatori per iterare su un array:
Vantaggi:
Svantaggi:
Nella versione rifattorizzata, vengono utilizzati controlli espliciti ai confini ad ogni passaggio:
Vantaggi:
Svantaggi: