ProgrammazioneSviluppatore C

Come funziona il meccanismo di passaggio degli argomenti nelle funzioni del linguaggio C? Come evitare errori di tipo durante il passaggio di variabili di diversi tipi, strutture e array?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Nel linguaggio C gli argomenti vengono sempre passati per valore. Questo significa che la funzione riceve una copia del valore dell'argomento. Per i tipi semplici (int, float) è evidente: le modifiche all'interno della funzione non influenzano la variabile originale. Per array e strutture ci sono delle sfumature:

  • Quando si passa un array a una funzione, in realtà si passa un puntatore al suo primo elemento, non l'intero array. Tuttavia, il puntatore stesso viene ancora passato per valore.
  • Per le strutture si può esplicitamente passare una copia (per valore), ma è più vantaggioso farlo tramite un puntatore — così la funzione può modificare la struttura originale.

Esempio: gestione di un array e di una struttura

#include <stdio.h> typedef struct { int a; int b; } Pair; void modifyArray(int arr[], int size) { arr[0] = 42; // modifica l'array originale } void modifyStruct(Pair s) { s.a = 100; // modifica solo la copia locale } void modifyStructPtr(Pair *s) { s->a = 200; // cambia l'originale tramite puntatore } int main() { int nums[2] = {1, 2}; Pair p = {10, 20}; modifyArray(nums, 2); modifyStruct(p); modifyStructPtr(&p); printf("nums[0]=%d, p.a=%d\n", nums[0], p.a); // nums[0]=42, p.a=200 return 0; }

Domanda trabocchetto.

Domanda: Se una funzione è dichiarata come void func(int arr[10]), l'array all'interno della funzione avrà sempre 10 elementi?

Risposta: No. La scrittura int arr[10] negli argomenti è in realtà equivalente a int *arr — la dimensione dell'array si perde al momento del passaggio. La funzione non conosce la reale lunghezza dell'array, quindi è sempre consigliabile passare un parametro aggiuntivo con la sua lunghezza. Altrimenti, ci possono essere accessi fuori dai limiti dell'array e UB.

Esempio:

void foo(int arr[10]) { printf("%d\n", arr[9]); // arr non contiene necessariamente 10 elementi! }

Storia

Nel progetto di gestione dei segnali, l'array veniva passato tramite funzione, pensando che la sua lunghezza fosse sempre la stessa, ma in un caso è stato passato un array più piccolo. Il risultato — accesso alla memoria oltre il limite, crash dell'applicazione e comportamento imprevedibile sul controller.


Storia

Nel software bancario si tentava di modificare una struttura passando per valore, invece che per puntatore. Le modifiche non venivano salvate, causando al modulo di elaborazione di non aggiornare lo stato dei conti, portando a errori nei calcoli.


Storia

Nel sistema di telemetria, uno studente ha aggiunto una funzione di pulizia dell'array, ma ha dimenticato di passare la lunghezza, e gli array avevano dimensioni diverse. L'errore è stato scoperto solo dopo aver raccolto una grande quantità di dati non validi e dopo lungo tempo di ricerca dei bug.