ProgrammazioneProgrammatore di sistema

Puoi spiegare in dettaglio i meccanismi di passaggio dei parametri nelle funzioni del linguaggio C: per valore e per puntatore? Fornisci esempi in cui l'uso di ciascun approccio è giustificato.

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Nel linguaggio C, i parametri in una funzione vengono sempre passati per valore — cioè una copia del valore dal codice chiamante viene passata alla funzione. Se è necessario modificare il valore di una variabile al di fuori della funzione, si utilizza il passaggio per puntatore.

Passaggio per valore

Quando si passa uno scalare (ad esempio, int), la funzione riceve la sua copia:

void foo(int a) { a = 10; } int main() { int x = 5; foo(x); // x == 5, non cambierà! }

Passaggio per puntatore

Per modificare il valore di una variabile si utilizza un puntatore:

void foo(int* a) { *a = 10; } int main() { int x = 5; foo(&x); // x == 10, valore cambiato! }

Quando utilizzare il puntatore

  • È necessario restituire più valori.
  • Modificare grandi strutture (risparmio di tempo e memoria, nessuna copia).
  • Per lavorare con array (vengono sempre passati come puntatore).

Domanda trabocchetto.

È un array un parametro di funzione passato per riferimento?

Molti rispondono "per riferimento", tuttavia in C un array nella firma della funzione non può essere passato per riferimento, essenzialmente degrada a un puntatore.

Risposta corretta:

Quando un array viene passato a una funzione, in realtà viene passato un puntatore al suo primo elemento. Cioè la funzione chiamata non conosce la dimensione reale dell'array, e qualsiasi modifica agli elementi dell'array si riflette sull'array originale.

void foo(int arr[]) { arr[0] = 100; } int main() { int a[3] = {1,2,3}; foo(a); // a[0] sarà 100! }

Storia


In un progetto, una funzione aggiornava i valori di un array dichiarato come int arr[10], ma nel codice chiamante l'array era di dimensioni inferiori. Poiché la funzione non conosceva la dimensione effettiva, si è verificato un overflow del buffer e un danno alla memoria.


In un altro caso, a causa del passaggio di una struttura per valore nella funzione, un intero blocco di memoria è stato copiato più volte, causando un calo delle prestazioni dell'applicazione.


Lo sviluppatore si aspettava che il passaggio di uno scalare "per riferimento" (tramite puntatore) garantisse l'immutabilità del valore originale, ma per errore ha modificato la memoria al di fuori dell'ambito (errore nell'aritmetica dei puntatori), portando a risultati imprevedibili.