Appel de fonction par référence en C

Bonjour à tous, futurs programmeurs ! Aujourd'hui, nous allons entreprendre un voyage passionnant dans le monde de la programmation C, en explorant spécifiquement le concept d' "Appel de fonction par référence". Ne vous inquiétez pas si vous êtes nouveaux en programmation ; je vais vous guider pas à pas, tout comme j'ai fait pour des centaines d'étudiants au fil des ans. Alors, prenez votre boisson favorite, asseyez-vous confortablement, et plongeons dedans !

C - Function call by reference

L'opérateur d'adresse (&) en C

Avant de pouvoir comprendre les appels de fonction par référence, nous devons nous familiariser avec un symbole très important en C : l'esperluette (&). Ce petit caractère est connu sous le nom d' "opérateur d'adresse", et il est comme une baguette magique qui révèle la localisation secrète de nos variables dans la mémoire de l'ordinateur.

Regardons un exemple simple :

#include <stdio.h>

int main() {
int age = 25;
printf("La valeur de age est : %d\n", age);
printf("L'adresse de age est : %p\n", &age);
return 0;
}

Dans ce code, nous n'imprimons pas seulement la valeur de age (qui est 25), mais aussi son adresse en mémoire. Le spécificateur de format %p est utilisé pour imprimer les adresses mémoires.

Lorsque vous exécutez ce programme, vous pourriez voir quelque chose comme :

La valeur de age est : 25
L'adresse de age est : 0x7ffd5e8e9944

Ce numéro étrange après "L'adresse de age est :" est en réalité une adresse mémoire ! C'est où votre ordinateur a décidé de stocker la variable age. Pensez-y comme l'adresse domicile de la variable dans le grand quartier de la mémoire de votre ordinateur.

Qu'est-ce qu'un pointeur en C ?

Maintenant que nous savons comment trouver l'adresse d'une variable, parlons des pointeurs. Si l'adresse est comme une adresse domicile, alors un pointeur est comme un navigateur GPS qui peut vous guider jusqu'à cette adresse.

En C, un pointeur est une variable qui stocke l'adresse mémoire d'une autre variable. Nous déclarons un pointeur en utilisant le symbole astérisque (*).

Voici un exemple :

#include <stdio.h>

int main() {
int age = 25;
int *ptr_age = &age;

printf("La valeur de age est : %d\n", age);
printf("L'adresse de age est : %p\n", &age);
printf("La valeur de ptr_age est : %p\n", ptr_age);
printf("La valeur pointée par ptr_age est : %d\n", *ptr_age);

return 0;
}

Dans ce code, ptr_age est un pointeur qui stocke l'adresse de age. Lorsque nous utilisons *ptr_age, nous demandons la valeur stockée à l'adresse pointée par ptr_age.

La sortie pourrait ressembler à ceci :

La valeur de age est : 25
L'adresse de age est : 0x7ffd5e8e9944
La valeur de ptr_age est : 0x7ffd5e8e9944
La valeur pointée par ptr_age est : 25

Voyez comment l'adresse stockée dans ptr_age correspond à l'adresse de age ? C'est parce que ptr_age pointe vers age !

Comment fonctionne l'appel de fonction par référence en C ?

Maintenant que nous comprenons les pointeurs, nous pouvons explorer les appels de fonction par référence. Lorsque nous appelons une fonction par référence, nous passons l'adresse d'une variable à la fonction, plutôt que sa valeur. Cela permet à la fonction de modifier directement la variable originale.

Regardons un exemple :

#include <stdio.h>

void increment(int *num) {
(*num)++;
}

int main() {
int x = 5;
printf("Avant increment : x = %d\n", x);
increment(&x);
printf("Après increment : x = %d\n", x);
return 0;
}

Dans ce code, nous passons l'adresse de x à la fonction increment. La fonction utilise ensuite cette adresse pour modifier directement la valeur de x.

La sortie sera :

Avant increment : x = 5
Après increment : x = 6

La fonction increment a pu changer la valeur de x dans la fonction main parce qu'elle a reçu l'adresse de x, pas juste une copie de sa valeur.

Mélanger les appels par valeur et par référence

En C, nous pouvons mélanger les appels par valeur et par référence dans la même fonction. Cela peut être utile lorsque nous voulons modifier certains paramètres mais pas d'autres.

Voici un exemple :

#include <stdio.h>

void modify(int *a, int b, int *c) {
(*a)++;
b++;
(*c)++;
}

int main() {
int x = 1, y = 2, z = 3;
printf("Avant modify : x = %d, y = %d, z = %d\n", x, y, z);
modify(&x, y, &z);
printf("Après modify : x = %d, y = %d, z = %d\n", x, y, z);
return 0;
}

Dans cet exemple, x et z sont passés par référence, tandis que y est passé par valeur.

La sortie sera :

Avant modify : x = 1, y = 2, z = 3
Après modify : x = 2, y = 2, z = 4

Notez comment x et z ont changé, mais y est resté le même ? C'est parce que la fonction a reçu seulement une copie de la valeur de y, pas son adresse.

Voici un tableau résumant les différences entre les appels par valeur et par référence :

Aspect Appel par Valeur Appel par Référence
Ce qui est passé Copie de la valeur Adresse de la variable
Peut modifier l'original Non Oui
Syntaxe function(variable) function(&variable)
Paramètre de fonction Variable normale Pointeur

Et voilà ! Nous avons couvert les bases des appels de fonction par référence en C. Souvenez-vous, comme pour toute nouvelle compétence, la pratique est clé. Essayez d'écrire vos propres fonctions qui utilisent l'appel par référence, et expérimentez avec différents scénarios. Avant de vous en rendre compte, vous manipulerez les adresses mémoires comme un pro !

Bonne programmation, et puissent vos pointeurs toujours pointer dans la bonne direction !

Credits: Image by storyset