logo

C Double pointeur (pointeur vers pointeur)

Comme nous le savons, un pointeur est utilisé pour stocker l'adresse d'une variable en C. Le pointeur réduit le temps d'accès à une variable. Cependant, en C, on peut également définir un pointeur pour stocker l'adresse d'un autre pointeur. Un tel pointeur est appelé double pointeur (pointeur vers pointeur). Le premier pointeur est utilisé pour stocker l'adresse d'une variable tandis que le deuxième pointeur est utilisé pour stocker l'adresse du premier pointeur. Comprenons-le par le schéma ci-dessous.

pointeur vers pointeur en c

La syntaxe de déclaration d’un double pointeur est donnée ci-dessous.

 int **p; // pointer to a pointer which is pointing to an integer. 

Considérez l'exemple suivant.

 #include void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf('address of a: %x
',p); // Address of a will be printed printf('address of p: %x
',pp); // Address of p will be printed printf('value stored at p: %d
',*p); // value stoted at the address contained by p i.e. 10 will be printed printf('value stored at pp: %d
',**pp); // value stored at the address contained by the pointer stoyred at pp } 

Sortir

 address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10 

Exemple de double pointeur C

Voyons un exemple où un pointeur pointe vers l'adresse d'un autre pointeur.

Exemple de pointeur vers pointeur C

Comme vous pouvez le voir dans la figure ci-dessus, p2 contient l'adresse de p (fff2) et p contient l'adresse de la variable numérique (fff4).

 #include int main(){ int number=50; int *p;//pointer to int int **p2;//pointer to pointer p=&number;//stores the address of number variable p2=&p; printf('Address of number variable is %x 
',&number); printf('Address of p variable is %x 
',p); printf('Value of *p variable is %d 
',*p); printf('Address of p2 variable is %x 
',p2); printf('Value of **p2 variable is %d 
',*p); return 0; } 

Sortir

 Address of number variable is fff4 Address of p variable is fff4 Value of *p variable is 50 Address of p2 variable is fff2 Value of **p variable is 50 

Q. Quel sera le résultat du programme suivant ?

 #include void main () { int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 int **pp = p; //Line 3 pp++; // Line 4 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 5 *pp++; // Line 6 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 7 ++*pp; // Line 8 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 9 ++**pp; // Line 10 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 11 } 

Explication

Question à double pointeur

Dans la question ci-dessus, l’arithmétique du pointeur est utilisée avec le double pointeur. Un tableau de 6 éléments est défini et pointé par un tableau de pointeurs p. Le tableau de pointeurs p est pointé par un double pointeur pp. Cependant, l'image ci-dessus vous donne une brève idée de la façon dont la mémoire est allouée au tableau a et au tableau de pointeurs p. Les éléments de p sont les pointeurs qui pointent vers chaque élément du tableau a. Puisque nous savons que le nom du tableau contient l'adresse de base du tableau, il fonctionnera donc comme un pointeur et la valeur peut être parcourue en utilisant *(a), *(a+1), etc. Comme le montre l'image , a[0] est accessible des manières suivantes.

paramètre Verilog
  • a[0] : c'est le moyen le plus simple d'accéder au premier élément du tableau
  • *(a) : puisqu'il stocke l'adresse du premier élément du tableau, nous pouvons accéder à sa valeur en utilisant un pointeur d'indirection dessus.
  • *p[0] : si a[0] doit être accessible en utilisant un pointeur p vers lui, alors nous pouvons utiliser l'opérateur d'indirection (*) sur le premier élément du tableau de pointeurs p, c'est-à-dire *p[0].
  • **(pp) : comme pp stocke l'adresse de base du tableau de pointeurs, *pp donnera la valeur du premier élément du tableau de pointeurs qui est l'adresse du premier élément du tableau d'entiers. **p donnera la valeur réelle du premier élément du tableau d'entiers.

En ce qui concerne le programme, les lignes 1 et 2 déclarent le tableau d'entiers et de pointeurs de manière relative. La ligne 3 initialise le double pointeur vers le tableau de pointeurs p. Comme le montre l'image, si l'adresse du tableau commence à 200 et que la taille de l'entier est 2, alors le tableau de pointeurs contiendra les valeurs 200, 202, 204, 206, 208, 210. Considérons que le l'adresse de base du tableau de pointeurs est 300 ; le double pointeur pp contient l'adresse du tableau de pointeurs, c'est-à-dire 300. La ligne numéro 4 augmente la valeur de pp de 1, c'est-à-dire que pp pointera désormais vers l'adresse 302.

La ligne numéro 5 contient une expression qui imprime trois valeurs, c'est-à-dire pp - p, *pp - a, **pp. Calculons-les chacun d'eux.

  • pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, c'est-à-dire que 1 sera imprimé.
  • pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, c'est-à-dire que 1 sera imprimé.
  • pp = 302, *pp = 202, *(*pp) = 206, c'est-à-dire que 206 sera imprimé.

Par conséquent, comme résultat de la ligne 5, la sortie 1, 1, 206 sera imprimée sur la console. À la ligne 6, *pp++ est écrit. Ici, il faut remarquer que deux opérateurs unaires * et ++ auront la même priorité. Par conséquent, selon la règle d’associativité, il sera évalué de droite à gauche. Par conséquent, l’expression *pp++ peut être réécrite sous la forme (*(pp++)). Puisque, pp = 302 qui deviendra désormais 304. *pp donnera 204.

À la ligne 7, encore une fois, l'expression est écrite qui imprime trois valeurs, c'est-à-dire pp-p, *pp-a, *pp. Calculons chacun d'eux.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, c'est-à-dire que 2 sera imprimé.
  • pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, c'est-à-dire que 2 sera imprimé.
  • pp = 304, *pp = 204, *(*pp) = 300, c'est-à-dire que 300 seront imprimés.

Par conséquent, comme résultat de la ligne 7, la sortie 2, 2, 300 sera imprimée sur la console. À la ligne 8, ++*pp est écrit. Selon la règle d'associativité, cela peut être réécrit comme (++(*(pp))). Puisque pp = 304, *pp = 204, la valeur de *pp = *(p[2]) = 206 qui pointera désormais vers a[3].

À la ligne 9, encore une fois, l'expression est écrite qui imprime trois valeurs, c'est-à-dire pp-p, *pp-a, *pp. Calculons chacun d'eux.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, c'est-à-dire que 2 sera imprimé.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, c'est-à-dire que 3 sera imprimé.
  • pp = 304, *pp = 206, *(*pp) = 409, c'est-à-dire que 409 sera imprimé.

Par conséquent, comme résultat de la ligne 9, la sortie 2, 3, 409 sera imprimée sur la console. À la ligne 10, ++**pp est écrit. selon la règle d'associativité, cela peut être réécrit comme (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. En d'autres termes, a[3] = 410.

À la ligne 11, encore une fois, l'expression est écrite qui imprime trois valeurs, c'est-à-dire pp-p, *pp-a, *pp. Calculons chacun d'eux.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, c'est-à-dire que 2 sera imprimé.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, c'est-à-dire que 3 sera imprimé.
  • À la ligne 8, **pp = 410.

Par conséquent, comme résultat de la ligne 9, la sortie 2, 3, 410 sera imprimée sur la console.

Enfin, le résultat du programme complet sera donné comme suit :

Java pgm

Sortir

 1 1 206 2 2 300 2 3 409 2 3 410