ProgrammationProgrammeur système

Pouvez-vous expliquer en détail les mécanismes de passage de paramètres dans les fonctions du langage C : par valeur et par pointeur ? Donnez des exemples où l'utilisation de chaque approche est justifiée.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Dans le langage C, les paramètres dans une fonction sont toujours passés par valeur — c'est-à-dire qu'une copie de la valeur du code appelant est transmise à la fonction. Si vous devez modifier la valeur d'une variable en dehors de la fonction, vous utilisez le passage par pointeur.

Passage par valeur

Lors du passage d'un scalaire (par exemple, int), la fonction reçoit sa copie :

void foo(int a) { a = 10; } int main() { int x = 5; foo(x); // x == 5, ne changera pas ! }

Passage par pointeur

Pour modifier la valeur d'une variable, on utilise un pointeur :

void foo(int* a) { *a = 10; } int main() { int x = 5; foo(&x); // x == 10, la valeur a changé ! }

Quand utiliser un pointeur

  • Besoin de retourner plusieurs valeurs.
  • Modifier de grandes structures (économie de temps et de mémoire, pas de copie).
  • Pour travailler avec des tableaux (ils sont toujours passés comme pointeur).

Question piégeuse.

Un tableau est-il un paramètre de fonction passé par référence ?

Beaucoup répondent "par référence", mais en C, un tableau dans la signature d'une fonction ne peut pas être passé par référence, en fait il se dégrade en pointeur.

Réponse correcte :

Quand un tableau est passé à une fonction, un pointeur vers son premier élément est en fait passé. Cela signifie que la fonction appelante ne connaît pas la taille réelle du tableau, et toute modification des éléments du tableau se reflète sur le tableau original.

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

Histoire


Dans un projet, une fonction mettait à jour les valeurs d'un tableau déclaré comme int arr[10], mais dans le code appelant, le tableau était de taille plus petite. Étant donné que la fonction ne connaissait pas la taille réelle, un débordement de tampon et une corruption de la mémoire se sont produits.


Dans un autre cas, en raison du passage d'une structure par valeur à une fonction, un grand bloc de mémoire a été copié plusieurs fois, ce qui a entraîné une baisse de performance de l'application.


Le développeur s'attendait à ce que le passage d'un scalaire par "référence" (via pointeur) garantisse l'immutabilité de la valeur d'origine, mais a accidentellement modifié en mémoire en dehors de la portée (erreur dans l'arithmétique des pointeurs), ce qui a conduit à des résultats imprévisibles.