Quando si passa un puntatore o un array a una funzione in C, in realtà viene passato un copia del valore del puntatore (cioè l'indirizzo di memoria), non l'array stesso o il contenuto della memoria. Storicamente, gli array in C non vengono passati per valore: al loro posto, viene passato un puntatore al primo elemento dell'array. Questo meccanismo risparmia memoria, ma può portare a effetti collaterali indesiderati se usato in modo errato.
Problema — confusione tra puntatori e array: spesso gli sviluppatori pensano che all'interno della funzione non sia possibile modificare l'array esterno o che la funzione conosca automaticamente la dimensione dell'array passato. In pratica, la funzione perde la dimensione originale dell'array e può facilmente andare oltre i suoi limiti.
Soluzione — passare sempre esplicitamente la dimensione dell'array come argomento separato, comprendere chiaramente la differenza tra una copia del puntatore e una copia dell'oggetto, non dimenticare che qualsiasi modifica attraverso un puntatore si riflette sui dati originali.
Esempio di corretta trasmissione di un array:
void print_array(const int* arr, size_t size) { for (size_t i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int nums[] = {1,2,3,4,5}; print_array(nums, sizeof(nums)/sizeof(nums[0])); return 0; }
Caratteristiche chiave:
Può una funzione conoscere la lunghezza di un array passato, se è stato dichiarato come int arr[10]?
Risposta: No, all'interno della funzione l'espressione sizeof(arr) restituirà la dimensione del puntatore, non dell'intero array. La dimensione deve essere passata separatamente.
Passare un array come int arr[] e come int arr nella funzione è la stessa cosa?*
Risposta: Sì, nella firma della funzione è equivalente: in entrambi i casi viene passato un puntatore a int. Le differenze sono solo nella sintassi.
Modificando gli elementi dell'array all'interno della funzione, si modificherà l'array originale?
Risposta: Sì, poiché è stato passato un puntatore, la funzione modifica la memoria a cui punta.
Il progetto ha implementato una funzione di inizializzazione degli array, determinando la dimensione all'interno della funzione tramite sizeof(arr) / sizeof(arr[0]). Durante i test, la funzione funzionava, ma quando elaborava altri array, sovrascriveva la memoria altrui o funzionava in modo errato.
Pro:
Contro:
La funzione accettava sempre la dimensione dell'array come parametro separato, la lunghezza era calcolata dalla parte chiamante. All'interno della funzione si lavorava solo con i parametri passati.
Pro:
Contro: