Rappelez-vous que le nom d'un tableau peut facilement se transformer en pointeur vers le premier élément dans la plupart des expressions (lire quelques exceptions où le nom du tableau ne se transforme pas en un pointeur vers le premier élément ? bien répondu par @ H 2 CO 3 ).
Pour une meilleure compréhension, considérez mes diagrammes :
Premièrement, supposons a
stockées en mémoire comme suit.
a
+----+----+----+----+---+
| 0 | 1 | 2 | 3 | 4 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲
| | | | |
a a+1 a+2 a+3 a+3
Déclaration static int *p[] = {a, a+1, a+2, a+3, a+4};
crée un nouveau tableau de pointeurs vers des entiers, avec les valeurs suivantes :
p[0] == a
p[1] == a + 1
p[2] == a + 2
p[3] == a + 3
p[4] == a + 4
Maintenant, p
peut également être supposé être stocké en mémoire, comme ci-dessous :
p
+----+----+----+----+-----+
| a |a +1| a+2| a+3| a+4 |
+----+----+----+----+-----+
▲ ▲ ▲ ▲ ▲
| | | | |
p p+1 p+2 p+3 p+4
Après l'affectation ptr = p;
les choses seront quelque chose comme ça :
p a
+----+----+----+----+-----+ +----+----+----+----+---+
| a |a +1| a+2| a+3| a+4 | | 0 | 1 | 2 | 3 | 4 |
+----+----+----+----+-----+ +----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
| | | | | | | | | |
p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+3
ptr
Notice: ptr points to first location in pointer array p[]
Expression : **ptr++ ;
Nous considérons maintenant l'expression **ptr++;
avant la première instruction printf.
-
ptr
est égal à p
qui est l'adresse du premier élément du tableau de pointeurs. Par conséquent, ptr
pointe vers le premier élément p[0]
dans un tableau (ou on peut dire ptr
== &p[0]
).
-
*ptr
signifie p[0]
et parce que p[0]
est a
donc *ptr
est a
( donc *ptr
== a
).
-
Et parce que *ptr
est a
alors **ptr
est *a
== *(a + 0)
== a[0]
c'est-à-dire 0
.
-
Note dans l'expression **ptr++;
nous n'attribuons pas sa valeur à la variable lhs.
Ainsi, l'effet de **ptr++;
est simplement identique à ptr++;
== ptr = ptr + 1
= p + 1
De cette façon, après cette expression ptr
pointant vers p[1]
(ou on peut dire ptr
== &p[1]
).
Imprimer-1 :
Avant le premier printf, les choses deviennent :
p a
+----+----+----+----+-----+ +----+----+----+----+---+
| a | a+1| a+2| a+3| a+4 | | 0 | 1 | 2 | 3 | 4 |
+----+----+----+----+-----+ +----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
| | | | | | | | | |
p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+3
ptr
Notice: ptr is equals to p + 1 that means it points to p[1]
Maintenant nous pouvons comprendre Premier printf :
-
ptr - p
sortie 1
parce que :
ptr = p + 1
donc ptr - p
== p + 1 - p
== 1
-
*ptr - a
sortie 1
parce que :
ptr = p + 1
donc *ptr
== *(p + 1)
== p[1]
== a + 1
Cela signifie : *ptr - a
= a + 1 - a
== 1
-
**ptr
sortie 1
parce que :
*ptr
== a + 1
du point-2
Alors **ptr
== *(a + 1)
== a[1]
== 1
Expression : *++*ptr ;
Après le premier printf, nous avons une expression *++*ptr;
.
Comme nous savons du point 2 ci-dessus que *ptr
== p[1]
. Donc, ++*ptr
(c'est-à-dire ++p[1]
) incrémentera p[1]
à a + 2
Comprendre à nouveau, dans l'expression *++*ptr;
nous n'assignons pas sa valeur à une variable lhs donc l'effet de *++*ptr;
est juste ++*ptr;
.
Maintenant, avant le deuxième printf, les choses deviennent :
p a
+----+----+----+----+-----+ +----+----+----+----+---+
| a |a+2 | a+2| a+3| a+4 | | 0 | 1 | 2 | 3 | 4 |
+----+----+----+----+-----+ +----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
| | | | | | | | | |
p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+3
ptr
Notice: p[1] became a + 2
Imprimer-2 :
Maintenant nous pouvons comprendre Deuxièmement printf :
-
ptr - p
sortie 1
parce que :
ptr = p + 1
donc ptr - p
== p + 1 - p
== 1
-
*ptr - a
sortie 2
parce que :
ptr = p + 1
donc *ptr
== *(p + 1)
== p[1]
== a + 2
Cela signifie : *ptr - a
== a + 2 - a
== 2
-
**ptr
sortie 2
parce que :
*ptr
== a + 2
du point-2
Alors **ptr
== *(a + 2)
== a[2]
== 2
Expression : ++**ptr ;
Expression actuelle ++**ptr;
avant le troisième printf.
Comme nous savons du point 3 ci-dessus que **ptr
== a[2]
. Donc ++**ptr
== ++a[2]
incrémentera a[2]
à 3
Donc avant le troisième printf les choses deviennent :
p a
+----+----+----+----+-----+ +----+----+----+----+---+
| a | a+2| a+2| a+3| a+4 | | 0 | 1 | 3 | 3 | 4 |
+----+----+----+----+-----+ +----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
| | | | | | | | | |
p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+3
ptr
Notice: a[2] = 3
Imprimé 3 :
Maintenant nous pouvons comprendre Troisièmement printf :
-
ptr - p
sortie 1
parce que :
ptr = p + 1
donc ptr - p
== p + 1 - p
== 1
-
*ptr - a
sortie 2
parce que :
ptr = p + 1
donc *ptr
== *(p + 1)
== p[1]
== a + 2
Cela signifie : *ptr - a
= a + 2 - a
== 2
-
**ptr
sorties 3
parce que :
*ptr
== a + 2
du point-2
Alors **ptr
== *(a + 2)
== a[2]
== 3
Modifier Note : La différence de deux pointeurs est de type ptrdiff_t
et pour cela, le spécificateur de conversion correct est %td
pas %d
.
Un point supplémentaire :
Je souhaite ajouter que je crois que cela sera utile pour les nouveaux apprenants.
Supposons que nous ayons les deux lignes suivantes avec un 4 de plus th printf dans votre code avant return 0;
**++ptr; // additional
printf("%d %d %d\n", ptr-p, *ptr-a, **ptr); // fourth printf
On peut vérifier ce code de travail @ Codepade cette ligne produit 2 2 3
.
Expression : **++ptr ;
Parce que ptr
est égal à p + 1
après l'incrément ++
opération ptr
devient p + 2
(ou on peut dire ptr
== &p[2]
).
Après cette opération de double déférence **
\==> **(p + 2)
== *p[2]
== *(a + 2)
== a[2]
== 3
.
Maintenant, encore une fois parce que nous n'avons pas d'opération d'affectation dans cette déclaration, l'effet de l'expression **++ptr;
est juste ++ptr;
.
Donc, chose après expression **++ptr;
devient comme ci-dessous dans la figure :
p a
+----+----+----+----+-----+ +----+----+----+----+---+
| a | a+2| a+2| a+3| a+4 | | 0 | 1 | 3 | 3 | 4 |
+----+----+----+----+-----+ +----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
| | | | | | | | | |
p p+1 p+2 p+3 p+4 a a+1 a+2 a+3 a+3
ptr
Notice: ptr is equals to p + 2 that means it points to p[2]
Impression 4 :
Envisager Forth printf que j'ai ajouté en question :
-
ptr - p
sortie 2
parce que :
ptr = p + 2
donc ptr - p
== p + 2 - p
== 2
-
*ptr - a
sortie 2
parce que :
ptr = p + 2
donc *ptr
== *(p + 2)
== p[2]
== a + 2
Cela signifie : *ptr - a
= a + 2 - a
== 2
-
**ptr
sorties 3
parce que :
*ptr
== a + 2
à partir du point 2 ci-dessus
Alors **ptr
== *(a + 2)
== a[2]
== 3