141 votes

Pointeur vers la précision du pointeur

J'ai suivi ce tutoriel sur comment un pointeur vers un pointeur de travail.

Permettez-moi de citer le passage pertinent:


    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;

Maintenant, nous pouvons définir

    int **ipp = &ip1;

et ipp points de ip1 des points de i. *ipp est ip1, et **ipp est i, ou 5. On peut illustrer la situation, avec notre familier de la boîte-et-flèche de notation, comme ceci:

enter image description here

Si ensuite nous dire

    *ipp = ip2;

nous avons changé le pointeur pointée par ipp (c'est - ip1) pour contenir une copie de l' ip2, de sorte qu'il (ip1) maintenant les points à l' j:

enter image description here


Ma question est: Pourquoi, dans la deuxième image, est - ipp pointe toujours vers ip1 mais pas ip2?

142voto

Robert S. Barnes Points 17244

Oublions pendant une seconde à la pointe de l'analogie. Ce qu'est un pointeur contient en réalité est une adresse mémoire. L' & est l'adresse de l'exploitant - dire qu'elle renvoie l'adresse mémoire d'un objet. L' * opérateur vous donne l'objet d'un pointeur désigne, c'est à dire un pointeur contenant une adresse, il renvoie l'objet à cette adresse mémoire. Ainsi, lorsque vous ne *ipp = ip2, ce que vous faites est - *ipp obtenir l'objet à l'adresse ipp qui ip1 et ensuite affecter à la ip1 de la valeur stockée dans ip2, qui est l'adresse de l' j.

Tout simplement
& --> Adresse de
* --> Valeur au

43voto

Skizz Points 30682

Parce que vous avez modifié la valeur pointée par pas la valeur de . Ainsi, pointe encore vers (la valeur de ), de valeur est désormais le même que de valeur, donc ils ont tous deux point à .

Ceci :

est identique :

21voto

michaeltang Points 1776

J’espère que ce morceau de code peut aider.

il affiche :

enter image description here

21voto

Eric Lippert Points 300275

Comme la plupart des questions de débutant dans le C balise, cette question peut être répondue par un retour aux principes de base:

  • Un pointeur est un type de valeur.
  • Une variable contient une valeur.
  • L' & opérateur transforme une variable dans un pointeur.
  • L' * opérateur transforme un pointeur sur une variable.

(Techniquement, je devrais dire "lvalue" au lieu de "variable", mais je pense qu'il est plus facile à décrire mutable emplacements de stockage comme des "variables".)

Nous avons donc des variables:

int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;

Variable ip1 contient un pointeur. L' & opérateur désactive i en un pointeur et que la valeur du pointeur est affecté ip1. Donc, ip1 contient un pointeur vers i.

Variable ip2 contient un pointeur. L' & opérateur désactive j en un pointeur et que le pointeur est affecté ip2. Donc, ip2 contient un pointeur vers j.

int **ipp = &ip1;

Variable ipp contient un pointeur. L' & de l'opérateur tourne la variable ip1 en un pointeur et que la valeur du pointeur est affecté ipp. Donc, ipp contient un pointeur vers ip1.

Résumons l'histoire:

  • i contient 5
  • j contient 6
  • ip1 contient "pointeur i"
  • ip2 contient "pointeur j"
  • ipp contient "pointeur ip1"

Aujourd'hui nous disons

*ipp = ip2;

L' * opérateur transforme un pointeur de retour dans une variable. On va chercher la valeur de ipp, ce qui est "pointeur ip1 et la transformer en une variable. Quelle variable? ip1 bien sûr!

Donc c'est simplement une autre façon de dire

ip1 = ip2;

Nous avons donc aller chercher la valeur de ip2. Quel est-il? "pointeur j". Nous affecter que la valeur du pointeur d' ip1, alors ip1 est maintenant "pointeur j"

Nous avons seulement changé une chose: la valeur de ip1:

  • i contient 5
  • j contient 6
  • ip1 contient "pointeur j"
  • ip2 contient "pointeur j"
  • ipp contient "pointeur ip1"

Pourquoi est - ipp toujours ip1 et pas ip2?

Une modification de la variable lorsque vous affectez à elle. Compter les devoirs; il ne peut y avoir plus de changements de variables qu'il y a des missions! Vous commencez par l'attribution d' i, j, ip1, ip2 et ipp. Ensuite, vous attribuez à l' *ipp, qui, comme nous l'avons vu, signifie la même chose que "assigner ip1". Puisque vous n'avez pas céder à l' ipp un deuxième temps, il n'a pas changé!

Si vous vouliez changer ipp , alors vous aurez à attribuer à l' ipp:

ipp = &ip2;

par exemple.

12voto

Lundin Points 21616

Mon opinion personnelle est que les photos avec des flèches pointant de cette façon, ou qui font des pointeurs plus difficile à comprendre. Il les rend semblent comme abstraite, des entités mystérieuses. Ils ne le sont pas.

Comme tout le reste dans votre ordinateur, les pointeurs sont des nombres. Le nom de "pointeur" est juste une façon élégante de dire "une variable contenant une adresse".

Par conséquent, permettez-moi de remuer les choses autour de en expliquant comment un ordinateur fonctionne réellement.

Nous avons une int, il a le nom d' i et la valeur 5. C'est stockée dans la mémoire. Comme tout ce qui est stocké dans la mémoire, il a besoin d'une adresse, ou nous ne serions pas en mesure de le trouver. Disons i se termine à l'adresse 0x12345678 et son copain j de la valeur 6 se termine juste après. En supposant un PROCESSEUR 32 bits où l'int est de 4 octets, et les pointeurs sont de 4 octets, alors les variables sont stockées dans la mémoire physique comme ceci:

Address     Data           Meaning
0x12345678  00 00 00 05    // The variable i
0x1234567C  00 00 00 06    // The variable j

Maintenant, nous voulons souligner à ces variables. Nous avons créer un pointeur de type int, int* ip1, et un int* ip2. Comme tout dans l'ordinateur, ces variables de pointeur obtenir alloué quelque part dans la mémoire. Supposons qu'ils finissent à la prochaine adjacentes adresses dans la mémoire, immédiatement après l' j. Nous avons mis les pointeurs pour contenir les adresses des variables précédemment alloué: ip1=&i; ("copier l'adresse de i dans ip1") et ip2=&j. Ce qui se passe entre les lignes est de:

Address     Data           Meaning
0x12345680  12 34 56 78    // The variable ip1
0x12345684  12 34 56 7C    // The variable ip2

Donc, ce que nous avons été tout de suite à 4 octets morceaux de mémoire contenant des nombres. Il n'y a pas de mystique ou magique flèches de nulle part en vue.

En fait, juste en regardant un vidage de la mémoire, nous ne pouvons pas dire si l'adresse 0x12345680 contient un int ou int*. La différence est la façon dont notre programme choisit d'utiliser le contenu stockée à cette adresse. (La tâche de notre programme est en fait juste de dire à la CPU de quoi faire avec ces chiffres.)

Ensuite, nous ajoutons encore un autre niveau d'indirection avec int** ipp = &ip1;. De nouveau, nous venons de passer une partie de la mémoire:

Address     Data           Meaning
0x12345688  12 34 56 80    // The variable ipp

Le modèle ne semblent familiers. Encore un autre bloc de 4 octets contenant un nombre.

Maintenant, si nous avions un vidage de la mémoire de la ci-dessus fictif peu de RAM, nous avons pu vérifier manuellement où ces pointeurs point. Nous coup d'oeil à ce qui est stocké à l'adresse de l' ipp variable et de trouver le contenu 0x12345680. Ce qui est bien sûr l'adresse où ip1 est stocké. Nous pouvons aller à cette adresse, vérifiez le contenu de là, et de trouver l'adresse d' i, puis, enfin, nous pouvons aller à cette adresse et de trouver le numéro 5.

Donc, si nous prenons le contenu de l'ipp, *ipp, nous allons obtenir l'adresse du pointeur de la variable ip1. En écrivant *ipp=ip2 nous copier ip2 en ip1, il est équivalent à ip1=ip2. Dans les deux cas, nous aurions

Address     Data           Meaning
0x12345680  12 34 56 7C    // The variable ip1
0x12345684  12 34 56 7C    // The variable ip2

(Ces exemples ont été donnés pour un big endian CPU)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X