Pointeur vers Pointeur (Double Pointeur) en C

Bonjour à tous, aspirants programmeurs ! Aujourd'hui, nous allons entreprendre un voyage passionnant dans le monde des pointeurs - plus précisément, des pointeurs vers des pointeurs. Je sais ce que vous pourriez penser : "Pointeurs ? Double pointeurs ? Ça a l'air d'un cauchemar !" Mais ne vous inquiétez pas, je promets de rendre cela aussi amusant et facile à comprendre que possible. Alors, prenez votre boisson préférée, mettez-vous à l'aise, et plongeons-y !

C - Pointer to Pointer

Qu'est-ce qu'un Double Pointeur en C ?

Imaginez que vous êtes dans une chasse au trésor. Vous avez une carte (appelons-la un pointeur) qui vous conduit à une cassette. Mais surprise ! À l'intérieur de la cassette, il y a une autre carte (un autre pointeur) qui vous conduit au trésor réel. C'est essentiellement ce qu'est un double pointeur - un pointeur qui pointe vers un autre pointeur.

En programmation C, un double pointeur est exactement ce que cela sonne - un pointeur vers un pointeur. C'est une variable qui stocke l'adresse d'un autre pointeur. Cela peut sembler un peu confus au début, mais ne vous inquiétez pas, nous allons le décomposer étape par étape.

Déclaration de Pointeur vers un Pointeur

Commençons par comment nous déclarons un double pointeur. La syntaxe est assez simple :

int **ptr;

Ici, ptr est un pointeur vers un pointeur vers un entier. Le premier astérisque * le rend un pointeur, et le second * le rend un pointeur vers un pointeur.

Exemple de Pointeur vers Pointeur (Double Pointeur)

Regardons un exemple simple pour mieux comprendre cela :

#include <stdio.h>

int main() {
int x = 5;
int *p = &x;
int **pp = &p;

printf("Valeur de x : %d\n", x);
printf("Valeur de x en utilisant p : %d\n", *p);
printf("Valeur de x en utilisant pp : %d\n", **pp);

return 0;
}

Sortie :

Valeur de x : 5
Valeur de x en utilisant p : 5
Valeur de x en utilisant pp : 5

Analysons cela :

  1. Nous déclarons un entier x et l'initialisons avec 5.
  2. Nous créons un pointeur p qui pointe vers x.
  3. Nous créons un double pointeur pp qui pointe vers p.
  4. Nous imprimons alors la valeur de x de trois manières différentes :
  • Directement en utilisant x
  • En utilisant le pointeur simple p (nous le déréférençons une fois avec *p)
  • En utilisant le double pointeur pp (nous le déréférençons deux fois avec **pp)

Toutes les trois méthodes nous donnent la même valeur : 5. C'est comme atteindre le trésor en utilisant différentes cartes !

Comment Fonctionne un Pointeur Normal en C ?

Avant de plonger plus profondément dans les double pointeurs, examinons rapidement comment fonctionnent les pointeurs normaux :

int y = 10;
int *q = &y;

printf("Valeur de y : %d\n", y);
printf("Adresse de y : %p\n", (void*)&y);
printf("Valeur de q : %p\n", (void*)q);
printf("Valeur pointée par q : %d\n", *q);

Sortie :

Valeur de y : 10
Adresse de y : 0x7ffd5e8e9f44
Valeur de q : 0x7ffd5e8e9f44
Valeur pointée par q : 10

Ici, q est un pointeur qui stocke l'adresse de y. Quand nous utilisons *q, nous accédons à la valeur stockée à cette adresse.

Comment Fonctionne un Double Pointeur ?

Maintenant, étendons cela aux double pointeurs :

int z = 15;
int *r = &z;
int **rr = &r;

printf("Valeur de z : %d\n", z);
printf("Adresse de z : %p\n", (void*)&z);
printf("Valeur de r : %p\n", (void*)r);
printf("Adresse de r : %p\n", (void*)&r);
printf("Valeur de rr : %p\n", (void*)rr);
printf("Valeur pointée par r : %d\n", *r);
printf("Valeur pointée par rr : %p\n", (void*)*rr);
printf("Valeur pointée par la valeur pointée de rr : %d\n", **rr);

Sortie :

Valeur de z : 15
Adresse de z : 0x7ffd5e8e9f48
Valeur de r : 0x7ffd5e8e9f48
Adresse de r : 0x7ffd5e8e9f50
Valeur de rr : 0x7ffd5e8e9f50
Valeur pointée par r : 15
Valeur pointée par rr : 0x7ffd5e8e9f48
Valeur pointée par la valeur pointée de rr : 15

Cela peut sembler un peu écrasant, mais analysons cela :

  1. z est un entier avec la valeur 15.
  2. r est un pointeur qui stocke l'adresse de z.
  3. rr est un double pointeur qui stocke l'adresse de r.
  4. *r nous donne la valeur de z (15).
  5. *rr nous donne la valeur de r (qui est l'adresse de z).
  6. **rr nous donne la valeur de z (15).

Pensez-y comme suit : rr pointe vers r, qui pointe vers z. Donc **rr est comme dire "suivez le premier pointeur, puis suivez le second pointeur, et donnez-moi la valeur là-bas".

Un Double Pointeur Se Comporte Comme un Pointeur Normal

Voici un petit secret : un double pointeur est juste un pointeur, mais au lieu de pointer vers un int ou un float, il pointe vers un autre pointeur. Cela signifie que nous pouvons faire toutes les mêmes choses avec les double pointeurs que nous pouvons avec les pointeurs normaux.

Par exemple, nous pouvons utiliser des double pointeurs avec des tableaux :

int main() {
char *fruits[] = {"Pomme", "Banane", "Cerise"};
char **ptr = fruits;

for(int i = 0; i < 3; i++) {
printf("%s\n", *ptr);
ptr++;
}

return 0;
}

Sortie :

Pomme
Banane
Cerise

Dans cet exemple, fruits est un tableau de pointeurs (chacun pointant vers une chaîne de caractères), et ptr est un pointeur vers un pointeur vers un char (qui peut pointer vers les éléments de fruits).

Pointeurs Multiniveaux en C (Un Triple Pointeur Est-il Possible ?)

Oui, vous pouvez avoir des triple pointeurs, des quadruple pointeurs et ainsi de suite ! Il n'y a pas de limite théorique aux niveaux d'indirection que vous pouvez avoir. Cependant, en pratique, il est rare de voir plus de double pointeurs.

Voici un exemple de triple pointeur :

int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;

printf("Valeur de x : %d\n", ***ppp);

Sortie :

Valeur de x : 5

Mais souvenez-vous, juste parce que vous pouvez, cela ne signifie pas que vous devriez. Plusieurs niveaux d'indirection peuvent rendre le code plus difficile à lire et à entretenir. Comme l'ancien adage de programmation le dit, "Tous les problèmes en informatique peuvent être résolus par un autre niveau d'indirection... sauf le problème de trop nombreux niveaux d'indirection !"

Conclusion

Félicitations ! Vous venez de naviguer dans les eaux difficiles des double pointeurs en C. Souvenez-vous, comme de nombreux concepts en programmation, les pointeurs vers des pointeurs peuvent sembler confus au début, mais avec de la pratique, ils deviendront une seconde nature.

Voici un tableau résumant les points clés que nous avons couverts :

Concept Syntaxe Description
Pointeur Normal int *p; Pointe vers un entier
Double Pointeur int **pp; Pointe vers un pointeur vers un entier
Déréférencement *p Accède à la valeur pointée par p
Double Déférencement **pp Accède à la valeur pointée par le pointeur que pp pointe
Opérateur d'Adresse &x Obtient l'adresse de x

Continuez à pratiquer, restez curieux, et souvenez-vous - chaque expert était un fois un débutant. Bon codage !

Credits: Image by storyset