Quelle est une bonne explication pour les pointeurs? [fermé]


72

Dans vos propres études (seul ou en classe), avez-vous eu un moment "ah ah" où vous avez finalement compris les indicateurs? Avez-vous une explication que vous utilisez pour les programmeurs débutants qui semble particulièrement efficace?

Par exemple, lorsque les débutants rencontrent pour la première fois des pointeurs en C, ils peuvent simplement ajouter &s et *s jusqu'à ce qu'il compile (comme je l'avais déjà fait moi-même). C’est peut-être une photo, ou un exemple vraiment bien motivé, qui a fait en sorte que les pointeurs "cliquent" pour vous ou votre élève. Qu'est-ce que c'était et qu'avez-vous essayé avant que cela ne semble pas fonctionner? Des sujets ont-ils été prérequis (par exemple, des structures ou des tableaux)?

En d'autres termes, que fallait-il pour comprendre le sens de &s et *quand les utiliser avec confiance? Apprendre la syntaxe et la terminologie ou les cas d'utilisation ne suffit pas, l'idée doit être intériorisée à un moment donné.


Mise à jour: j'aime beaucoup les réponses jusqu'à présent; s'il vous plaît, continuez. Il y a beaucoup de bonnes perspectives ici, mais je pense que beaucoup sont de bonnes explications / slogans pour nous-mêmes après que nous ayons intériorisé le concept. Je cherche les contextes détaillés et les circonstances quand cela vous est apparu.

Par exemple:

Je n'ai que quelque peu compris les pointeurs syntaxiquement en C. J'ai entendu deux de mes amis expliquer des pointeurs à un autre ami, qui a demandé pourquoi a structétait passé avec un pointeur. Le premier ami a parlé de la nécessité de le référencer et de le modifier, mais il ne s'agissait que d'un bref commentaire de l'autre ami qui m'a frappé: "C'est aussi plus efficace." Passer 4 octets au lieu de 16 octets était le dernier changement conceptuel dont j'avais besoin.


16
Méthode 'Shotgun': lancez partout jusqu'à ce que cela fonctionne.
Michael K

15
@ Michael: Ouais, bonne chance avec ça.
Robert Harvey

8
Cette question se pose peu de temps après au début de chaque semestre sur SO. La dernière incarnation est ici: stackoverflow.com/questions/4118647/…
Tim Post

10
Quelle est une bonne explication pour les pointeurs? Brian Kernhigan et Dennis Ritchie détestent les ingénieurs en logiciel.
Adam Crossland

3
Il a "cliqué" pour moi après avoir passé du temps en code machine pas à pas dans le débogueur. Oui, je connaissais les bases de l’architecture informatique: j’ai appris à assembler sur Commodore 64 et x86 ASM était assez simple par la suite. Donc, je connaissais déjà le concept d'une "adresse", je ne comprenais tout simplement pas comment il était mappé sur les constructions syntaxiques de C.
Zvrba

Réponses:


25

Diagramme mémoire en tant que grille

Habituellement, je représente la mémoire sous forme de "grille", ce qui me permet de créer des adresses, de mettre en évidence différents espaces mémoire et d'écrire dans les valeurs des cellules (ou même plus loin, leurs représentations binaires) et de relier les pointeurs en mémoire aux valeurs qu'ils définissent. pointez sur. (Et puis toujours mentionner que c'est une simplification).

C'est généralement un moment "ohhhh" pour la plupart de mes étudiants.

Symbole jonglant

Ensuite, quand il s’agit de leur demander de cesser d’oublier comment utiliser & et *, c’est très simple: présentez-le de la même manière que les calculs mathématiques ou physiques. Si vous divisez une distance en km par un temps en heure, vous obtenez une vitesse en km / h. Ce qui est doit être dehors. Facile.

printf à la rescousse

Faire juste quelques exemples de base qui représentent visuellement ce que vous avez expliqué avec cela les réconfortera dans ce qu'ils pensent avoir compris, ou leur donnera l'occasion de dire "ah, je ne comprends pas celui-ci".

Être étendu

Couvrez les pointeurs pour les types simples et assurez-vous qu'ils comprennent la différence entre l'adressage et la taille d'un type de données, puis les structures, les tableaux, puis plusieurs niveaux.

Puis lancez l'arithmétique de pointeur.


Addendum: Récursion

J'explique généralement la récursion de la même manière, en utilisant une représentation visuelle. Demandez-leur d’imprimer l’alphabet à l’aide d’une fonction prédéfinie permettant d’écrire un seul caractère, puis de leur demander de l’imprimer dans l’ordre inverse en ne modifiant que deux lignes.

Habituellement, il y a un "qu'est-ce que ...?" moment, et lorsque vous ajoutez juste un autre paramètre à votre printf pour imprimer des valeurs numériques et indenter les étapes, cela devient un soupir de soulagement.


Alternatives: le modèle Play-Doh et les gobelets d'eau

Dans une université, certains de mes collègues ont montré aux étudiants une vidéo expliquant les pointeurs et les accès à la mémoire à l'aide de la pâte play-doh. C'était incroyablement intelligent et bien fait, bien que je n'aie jamais vraiment utilisé cette technique, sauf pour les très jeunes apprenants intéressés par la programmation (mais en général ceux pour qui je ne les mènerais pas vers une langue utilisant des indicateurs trop tôt). En utilisant essentiellement de minuscules boules de play-doh que vous pouvez attacher à d’autres plus grosses boules de play-doh représentant des espaces mémoire, et que vous pouvez combiner pour les lier (comme dans une structure de données liée) ou pour les fusionner (comme dans une structure contiguë). espace mémoire). L'utilisation de différentes couleurs pour les espaces mémoire pointés et les pointeurs aident également. Mais je pense toujours que la mémoire en tant que grille fonctionne mieux, comme vous pouvez clairement montrer que le pointage est vraiment une question "d'adressage", comme sur une "carte / grille". Alors que le mode Play-doh les confond toujours dans l'idée que les choses se "touchent" vraiment en mémoire.

Un collègue a également utilisé directement le sujet de la coupe d’eau, mais je ne sais pas si elle l’a inventée. C'était une approche intéressante, mais j'ai remarqué que de nombreux étudiants étaient restés perplexes devant l'explication. Quelque chose ressemble à la technique de la tasse à café DevSolo . Mais je pense que c’est en réalité une idée trompeuse lorsque vous incitez les étudiants à confondre conteneurs, structures de données, pointeurs et tableaux. Je suppose que c’est une approche intéressante pour expliquer les tableaux au début, mais je ne m'en tiendrai pas très longtemps.


Wow, merci pour la prime. Heureux que la réponse ait été appréciée.
Hayem

Dessinez-le: | cela ressemble à un bon enseignement!
Spooks

80

Quelqu'un beaucoup plus sage que je ne l'ai dit une fois:

La religieuse Wu Jincang a demandé au Sixième Patriache Huineng: "J'ai étudié le sutra Mahaparinirvana pendant de nombreuses années, mais il y a de nombreux domaines que je ne comprends pas très bien. S'il vous plaît, éclairez-moi."

Le patriarche répondit: "Je suis illettré. Lis-moi les caractères et je pourrai peut-être en expliquer le sens."

La nonne dit: "Vous ne pouvez même pas reconnaître les personnages. Comment pouvez-vous alors en comprendre le sens?"

"La vérité n'a rien à voir avec les mots. La vérité peut être assimilée à la lune brillante dans le ciel. Les mots, dans ce cas, peuvent être assimilés à un doigt. Le doigt peut indiquer l'emplacement de la lune. Cependant, le doigt n'est pas le lune. Pour regarder la lune, il est nécessaire de regarder au-delà du doigt, non?


13
+1 pour déréférencer la lune. +1 pour le koan, si je pouvais.
Tim Post

14
Quel est le son d'un vote up doigt?
Adam Crossland

3
@Adam, cela dépend si vous utilisez une souris ou un trackpad.
Daniel Joseph

7
@Frank C'était une excellente citation. Néanmoins, je pense que cela n’aidera pas à saisir l’idée. Spécialement à quelqu'un de nouveau aux pointeurs.
Gulshan

11
C'est une belle histoire ... mais je soupçonne que les gens votent positivement à cause de cela, plutôt que parce que cela explique bien les indicateurs.
Kyralessa

46

J'ai trouvé que les diagrammes étaient très utiles. Exemple:

diagramme de pointeur


Ce type de diagramme m'a aidé à voir que les pointeurs étaient leur propre variable, mais contenaient une valeur qui était l'emplacement d'un autre objet, un tableau ou une chaîne. De plus, une fois terminé au crayon, je pourrais l'utiliser pour tracer mon programme sur papier, ou sur un tableau noir / blanc.


4
Soit la valeur dans "pointeur" doit être 4, soit les indices de tableau (ou adresses mémoire) doivent commencer à 0. Sinon, comment un pointeur qui contient la valeur 3 peut-il pointer vers l'emplacement 4?
MAK

++ C'est exactement comme ça que j'allais l'expliquer. J'ai commencé à Fortran (pour le meilleur ou pour le pire!). En Fortran, il y a bien longtemps, nous utilisions des tableaux parallèles au lieu des tableaux de structures (rien de nouveau ). Si un tableau contenait un index "une autre ligne" dans les tableaux, nous l'appelions un "pointeur" et c'était passionnant. Nous avons créé des listes de liens, des arbres, par exemple.
Mike Dunlavey

2
Je trouve que les pointeurs sont mieux expliqués en utilisant des images indiquant ce qui est stocké où et des flèches pour indiquer où les pointeurs pointent.
Gablin

32

Quand j'ai «appris» pour la première fois sur les pointeurs, je me suis senti poussé à le comprendre. Mon université avait pris la décision longtemps avant que je m'inscrive pour centrer le programme sur Java. Ainsi, lorsque mon professeur de Data Structures a donné une conférence sur le C et nous a demandé de mettre en place une liste XOR avec des pointeurs, j'avais l'impression de vouloir faire quelque chose. bien au- dessus de ma tête.

J'ai compris la définition:

Un pointeur est une variable qui contient l'adresse d'une variable.

Mais je n'ai toujours pas compris une grande partie du concept. En regardant en arrière, je pense que cela s’est centré sur trois choses:

  1. Qu'est - ce exactement est un emplacement de mémoire? (À l'époque, je n'ai pas suivi de cours d'organisation informatique)

  2. La syntaxe maladroite (Donc, euh ... pourquoi est-elle définie exactement comme "int * ip" mais ensuite, je me réfère à la variable par "ip"?)

  3. En quoi est-il avantageux de stocker l'adresse d'une variable plutôt que de simplement utiliser la variable?

Ce n’est que lorsque j’ai acheté le livre K & R et complété tous les problèmes que j’ai vraiment compris les indicateurs. Outre le fait que je suivais depuis longtemps le cours d’organisation informatique (ce qui, à mon avis, devrait être nécessaire avant d’apprendre le C), cela tenait en partie au fait que j’ai réalisé que les pointeurs pouvaient être utilisés pour des fonctions, des tableaux, des structures ... faire des choses utiles et pas simplement comme stockage pour les adresses de variables ordinaires.

Mais mon moment "aha" était de loin la façon dont K & R a expliqué la syntaxe délicate de la définition d'un pointeur simple. J'ai pris des notes tout au long du livre (dans lesquelles je reformule les points que le livre a formulés dans mes propres mots afin de renforcer ma compréhension), et voici celle qui se rapporte à cela:

Un pointeur est une variable qui contient une adresse à une variable. Un pointeur est à la fois défini et déréférencé (donnant la valeur stockée à l'emplacement de mémoire sur lequel il pointe) avec l'opérateur '*'; l'expression est mnémonique.

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

J'avais toujours senti que je ne pouvais pas saisir complètement les concepts plus avancés de pointeurs avant d'avoir quelque chose d'aussi élémentaire enraciné dans ma tête. Cela m'avait ennuyé sans cesse après cette mission (ce que je n’avais pas très bien fait, soit dit en passant;)) pourquoi "* ip" n’existait pas juste après que je pensais avoir défini "* ip". La maîtrise de cette information est essentielle pour les concepts plus avancés impliquant des pointeurs, tels que les pointeurs de fonction et les définitions plus complexes telles que celle-ci:

char (*(x())[])()

Au total, je pense que le concept de pointeurs nécessite:

  1. Compréhension de base de la configuration de la mémoire dans un ordinateur (et de ce qu’est la mémoire).

  2. Connaissance de la puissance des indicateurs (utilisation dans le monde réel, pas simplement d'un autre concept abstrait qu'ils apprennent pour apprendre).

  3. Déchiffrer les hiéroglyphes familièrement appelés "une définition d'un pointeur"

Donc dans l’ensemble, je pense qu’il devrait y avoir au moins 3 moments "aha" lors de l’apprentissage des pointeurs. Je suis toujours étudiant, alors je pensais que vous apprécieriez le point de vue de quelqu'un qui est encore (relativement) tout à fait en train d'apprendre le concept.


+1 pour le 3 "Ah ha!" les mois. Les pointeurs de Groking sont divisés en couches. J'ai "compris" des points pendant longtemps avant de me rendre compte que je ne comprenais que la moitié des pointeurs sur des pointeurs :)
Binary Worrier

Je pense que vous avez tout à fait raison en ce sens qu'une très grande partie de "ne pas comprendre les pointeurs" est en train de trébucher sur la syntaxe C étrange. [Pense: Je me demande combien il serait difficile de parler avec ce genre de syntaxe: PointerTo<int> a]
Benjol

D'accord, @Benjol. Je suis surpris que la syntaxe int* ipne soit pas plus commune. J'ai finalement commencé à comprendre les pointeurs une fois que j'ai vu le code qui était formaté comme ceci. Ensuite, je pourrais le lire comme "ip est de type int pointer."
Jacob

19

Les pointeurs sont un peu comme les raccourcis d’application sur votre bureau. Supprimez le raccourci et la cible existe toujours. Démarrez le raccourci et la cible est lancée.

J'explique toujours le fonctionnement de ceci en créant simplement un fichier txt sur mon bureau et deux raccourcis vers le fichier. Après avoir copié et supprimé les raccourcis, vous pouvez voir que les gens comprennent l’idée derrière les «références».

Une fois que le groupe comprend la base des raccourcis, vous pouvez commencer à expliquer les pointeurs comme vous le souhaitez. Ils vont probablement le comprendre assez facilement.


Ce n'est pas une mauvaise analogie. Quelques points à ajouter à toute personne prenant cela littéralement, un "lien dur" pointera toujours vers sa cible même s'il change de répertoire, un pointeur pointera vers la mémoire d'origine même si l'objet a été déplacé. Un "lien dur" vous indiquera que la cible n'existe plus, un pointeur de pointeur en suspens doit être défini sur NULL.
Snmcdonald

Un lien physique est comme un pointeur intelligent compté de références
jk.

1
+1 Une des meilleures analogies pratiques pour expliquer les pointeurs. Je suis sûr que les étudiants comprendraient immédiatement l'idée car cette fonctionnalité est la plus utilisée par tout le monde.
Karthik Sreenivasan

13

Il y a 8 à 10 ans, j'ai enseigné un cours d'introduction «C» dans un collège communautaire. C'était toujours un sujet amusant à explorer. Ce qui a semblé fonctionner le mieux, c'est après avoir discuté avec un collègue à quelques reprises, a été d'utiliser une tasse de café et votre main.

J'ai utilisé l'analogie d'une tasse de café (ou une rangée de celles-ci pour les tableaux) comme variable (elle peut contenir quelque chose). J'ai ensuite utilisé ma main, qui pouvait aussi tenir quelque chose ou, en allongeant mon index pour "pointer" une tasse de café.

Une main proche était nulle, un doigt pointé sur ma tête (un simulacre de pistolet) était un pointeur qui pendait.

Puis, avec quelques démonstrations et déplacements dans le débogueur, la plupart des utilisateurs ont cliqué.


3
Vous m'avez déjà confondu.
kirk.burleson

1
@Kirk, comment ça va? laissez-moi voir si je peux éclaircir.
DevSolo

4
++ Rien ne vaut l'enseignement pour vous faire penser à ces choses.
Mike Dunlavey

Un de mes professeurs à l'université a fait la même chose, en utilisant des étudiants (dont l'un était "Niel", pour un rire supplémentaire), à ​​la place de la tasse à café. En pointant du doigt l’audience, on pouvait voir un pointeur en suspens, parce qu’il pouvait indiquer n'importe quoi.
Kaz Dragon

2
Un pointeur en suspens revient plus à pointer Neil vers lui que de le faire quitter son fauteuil sans changer de direction ... puis d'essayer de suivre ce pointeur et d'interpréter ce que vous trouvez là en tant que Neil, peu importe qui y est arrivé.
Jon Purdy

10

Je suis vraiment très inquiète quand j'entends la question "Comment avez-vous compris les indicateurs". J'ai toujours pensé que le concept était incroyablement simple et que l'évolution logique des langages donnait un grand pouvoir aux programmeurs.

Ce qui m'inquiète, c'est que je n'ai jamais trouvé difficile de comprendre le concept de pointeurs. Alors, quand vous êtes ici "quand l'avez-vous finalement eu" encore et encore, vous commencez à penser:

Est-ce que je l'obtiens réellement? Peut-être que je n'ai jamais fait?

Peut-être que la raison pour laquelle le concept semble être délicat, c'est parce que nous continuons à dire à tous ceux qui ne l'ont pas encore rencontré que les pointeurs sont si difficiles, et qu'il y a cent façons d'apprendre.

Juste pour lancer cette idée, bien sûr, personnellement, j'aime un bon diagramme et Steve Gibson fait toujours un travail fantastique pour expliquer n'importe quoi !


Intéressant ... quelle langue avez-vous utilisé à l'époque? Je pense que la syntaxe C intercepte beaucoup de gens. Si vous connaissiez d'abord le montage, je pourrais voir cela comme une des raisons. [BTW, je veux voter, mais j'ai atteint mon plafond pour aujourd'hui.]
Macneil

Chose intéressante, je ne connaissais pas les indicateurs "dangereux" depuis longtemps, travaillant en Python (et Java à l'Université). Ensuite, j'ai pris un module "méthodes orientées objet" qui utilisait le langage C ++ comme langage de choix et s'y est plongé directement.
Marcus Whybrow

Aussi, je pense que comprendre la façon dont un programme est représenté en mémoire peut certainement aider, mais je dirais plutôt que comprendre pourquoi les pointeurs sont un ajout utile à une langue est l'angle le plus efficace, car vous subissez le même processus comme les concepteurs d'origine.
Marcus Whybrow

+1 Je ne sais pas pourquoi les gens pensent que les pointeurs sont difficiles ou mystérieux.
Ggambett

Oui, les pointeurs ont toujours été si simples et utiles que je ne peux imaginer penser qu’ils ont quelque chose de "dur". Je déteste quand un enseignant de n'importe quel cours dit "maintenant, c'est un peu compliqué" parce que c'est tellement subversif. Il suffit d’enseigner ces maudites choses et de laisser les étudiants décider eux-mêmes s’ils pensent que c’est délicat.
Jon Purdy

7

Je n'ai jamais vraiment eu de problème avec les pointeurs en C, mais c'est peut-être parce que je devais d'abord apprendre l'assembleur. C'était en fait un soulagement de ne plus avoir à gérer moi-même les adresses. Alors peut-être que la solution (en supposant que vous enseigniez cela) est de donner aux élèves un langage d'assemblage imité avec lequel travailler. Ils vont comprendre dans le processus d'écriture quelque chose de plus sophistiqué que « Bonjour, monde. »


+1 pour adapter une abstraction plus primitive, plutôt que d'essayer d'utiliser une analogie.
Type anonyme

Dans mon lycée, une unité d'informatique a été consacrée à l'étude d'un ordinateur de boîte d'allumettes , qui peut être enseigné à partir du tableau noir sans jamais toucher ou faire intervenir un véritable ordinateur.
Rwong

@ Larry Coleman, Assemblée !!!!!!!!!!! Je veux l'essayer avant C. Merci de me dire par où commencer l'apprentissage. Ebooks gratuits, PDF gratuit? IDE? S'il vous plaît!!!!!!!!!!!!!!!!!!!
Spacez Ly Wang

7

Un pointeur est une variable dont la valeur est l'adresse mémoire d'une autre variable.


Élégant, pourquoi compliquer les choses.
Bjarke Freund-Hansen

Si les pointeurs ne semblent pas immédiatement intuitifs et utiles, ils ont été mal expliqués.
Jon Purdy

6

Comment j'ai vraiment appris sur les pointeurs? En écrivant un étudiant de première année de compilation simple.

Comment expliquer les pointeurs en termes simples? J'aime l'analogie (datée?) D'un catalogue de bibliothèque stocké sur des fiches. Chaque carte ("pointeur") contient des informations sur l'emplacement d'un livre ("données"), mais ne contient pas le livre lui-même. Si vous modifiez la carte ("arithmétique de pointeur"), il ne fait que modifier le livre indiqué et n'a aucun impact sur le livre lui-même. Veillez simplement à ne pas foirer l'adresse et à ne pas pointer vers un livre inexistant. ou même la mauvaise bibliothèque. Cependant, si vous suivez "l'adresse" sur la carte et allez dans la partie appropriée de la bibliothèque ("déréférencer le pointeur"), vous pouvez voir / modifier le livre lui-même.


+1 pour la mémoire de mon cours de CS où j'avais exactement cette explication
Gary Rowe

C'est bien dans un sens, mais un peu trompeur, car les cartes ne disent pas vraiment où se trouve le livre. Vous devez toujours exécuter un algorithme de recherche orienté baskets. Peut-être que cela modélise mieux une base de données en faisant référence à un objet stocké par une clé (numéro d'appel).
DarenW

+1 L'analogie conserve le même concept que celui expliqué par Barfieldmv, mais avec une approche plus réaliste.
Karthik Sreenivasan

5

Je supposerai que quelqu'un qui apprendra des pointeurs sait quelles sont les variables normales et comment elles fonctionnent en C. Essayons maintenant de définir des pointeurs avec certains de ses attributs.

  • Ce sont aussi des variables, mais de nature différente. Supposons qu'il y a deux couches dans l'espace variable. Les variables normales de différents types résident dans la couche supérieure et les pointeurs dans la couche inférieure. Comme ce chiffre

    texte alternatif

  • Comme son nom l'indique, les pointeurs peuvent indiquer quelque chose. Comme notre doigt peut pointer sur un objet. Quelles sont les choses qu'ils désignent? Ce sont les variables normales. En bref, "Les pointeurs pointent vers des variables normales".

  • Comme les variables normales, les pointeurs ont le même nombre de types comme int, char ou float. Et un pointeur d'un type spécifique ne peut pointer que sur le même type de variables.
  • Un pointeur peut pointer sur une variable et plus tard, le même pointeur peut pointer sur une autre variable. Juste le type devrait être le même. Ainsi, l'association d'un pointeur avec une variable n'est pas permanente et peut être modifiée.
  • Alors, comment un pointeur est déclaré? Presque comme des variables normales. Vous devez faire précéder le nom d'un astérisque ( *). Comme-

    int *pointer;
    
  • Alors, comment un pointeur est associé à une variable? Utiliser l' &opérateur avant la variable comme cette déclaration-

    pointer = &variable;
    
  • Comment un pointeur est utilisé en pointant sur une variable? Cela se fait également en faisant précéder le nom d'un astérisque ( *). Ensuite, il peut être utilisé à la place de la variable sur laquelle il pointe maintenant-

    *pointer = var1 + var2;
    

    au lieu de

    variable = var1 + var2;
    
  • Maintenant, jouez avec des pointeurs avec du code. Il suffit de vous habituer à ces caractéristiques des pointeurs maintenant. Jusqu'ici, nous parlons de ce que font les pointeurs. Une fois que cela vous convient, commencez à étudier comment les pointeurs pointent sur une variable et comment ils réagissent si des opérations arithmétiques normales leur sont appliquées. Ensuite, optez pour la relation entre les pointeurs et les tableaux et les pointeurs vers les pointeurs.

C’est tout ce que je vais suggérer à propos des indicateurs.


Je voulais suivre le processus "d'abord ce qu'il fait puis comment". Abstraction!
Gulshan

5

Édité à l'appui de l'exigence révisée de la question

Mon chemin vers la compréhension "post-pointeur" (si je me souviens bien) s'est passé comme ceci. J'avais une expérience simple de la programmation d'assemblage à partir de l'époque où je bricolais encore avec une BBC Micro . J'avais donc le concept de mémoire comme un tas de boîtes (voir ci-dessous pour cela). Cela a été renforcé par l'utilisation de tableaux. Cependant, j'entrais dans le monde de C et je devais composer avec des chaînes, ce qui signifiait des indicateurs. En BASIC, c’était trivial, en assembleur je n’ai jamais eu à travailler avec eux, et maintenant en C classique, c’est tout ce qu’il faut savoir. Ah, mais je peux revenir aux tableaux avec des chaînes (terminées par null) comme ceci:

char s[] = "Hello, world!";
printf("%s",s);

Tout va bien, c'est juste un tableau de caractères (8 bits par caractère dans mon petit monde) avec un caractère zéro à la fin pour montrer où il se termine. Le printf prend juste ce tableau et le survole en l’imprimant. Mais que faire si je veux passer cette chaîne dans une fonction?

void print_str(char* p) {
  printf("%s",p);
}

C’est ce que dit le manuel, mais de quoi s'agit-il? Hmm, car * signifie "pointeur sur un personnage". OK ... m'a perdu. Ensuite, je me suis rendu compte que le caractère * rend p équivalent à s [0]. OK, je peux l'utiliser, mais je n'ai toujours pas déterminé ce que sont les pointeurs. Je veux dire, comment définir des données avec l'une de ces choses? De nouveau au manuel ...

char* p = "Hello World!";

En écrivant ce qui précède, je me dis "déclarez un pointeur sur un caractère et réglez-le sur ce tableau de caractères". D'une certaine manière, ce pointeur supprime la nécessité d'un tableau. Je suppose que c'est le compilateur qui fait des trucs pour moi pour changer. Alors, comment puis-je changer le tableau avec ce pointeur? Je sais que je pourrais utiliser la version tableau

 s[2] = 'L'; 

mais quel est l'équivalent dans "pointeur parler"? De nouveau à ce manuel ...

*(p+2) = 'L';

Je suppose que * signifie simplement "le contenu de l'adresse de la mémoire" et (p+2)est s[2]. Ce qui signifiait que le pointeur p était ... juste ... une ... adresse ... bong!

Qu'il y ait le son de l'illumination. J'ai soudainement brouillé les pointeurs (c'était il y a longtemps, nous, les anciens, ne "grokons" que plus tard). C'était juste indirection.


Original:

OK, mon 2c vaut la peine:

Imagine la mémoire est un tas de boîtes. Chaque case a un numéro sur le côté (l'adresse). Chaque case contient un numéro (le contenu). Vous pouvez travailler avec ces boîtes de 2 manières: variables (je veux le contenu de la boîte N), pointeurs (je veux le contenu de la boîte quel que soit le contenu de la boîte N ). Les pointeurs sont simplement indirectionnels.

Et pour la grande réponse qui couvre tout ce que vous aurez besoin de savoir - lisez ceci .


++ C'est plus ou moins la façon dont j'ai enseigné la matière.
Mike Dunlavey

Article édité pour répondre aux exigences de l'OP.
Gary Rowe

Quel manuel utilisiez-vous pour ajouter des caractères NUL supplémentaires à la fin de vos chaînes?
Rob Gilliam

@raimesh Un très vieux (vers 1991). Je ne me souviens plus lequel.
Gary Rowe

1991? Ce n'est pas vieux pour un manuel en langage C - la 1ère édition de K & R a été publiée en 1978! Je suis juste intrigué par le fait qu’il existe un manuel qui suggère que vous deviez mettre \ 0 à la fin de vos constantes de chaîne. (En fait, en regardant à nouveau, aviez-vous l'intention de mettre \ n?)
Rob Gilliam

4

Obtenez quelques petits blocs de bois.

Ajoutez des crochets en métal à une extrémité et des yeux en métal à l'autre.

vous pouvez maintenant faire une liste chaînée dans des choses avec lesquelles vous pouvez jouer.

Essayez d'expliquer avec cet accessoire physique. J'ai souvent souhaité avoir cela lorsque j'enseignais des pointeurs aux étudiants de première année.

Le petit crochet en métal est le pointeur, le bloc de bois indiqué.

Je défie quiconque de ne pas l'obtenir après avoir joué avec les blocs.


4

J'ai simplifié la vie en retirant tout le contenu et en commençant à traiter le pointeur comme une autre variable plutôt que comme une entité magique (il y a très longtemps en 11e année). Il suffit de savoir 3 choses:

  1. Le pointeur est une variable qui stocke l'adresse d'une autre variable (ou de n'importe quelle adresse).
  2. * est utilisé pour obtenir la valeur à l'emplacement de la mémoire qui est stockée dans la variable de pointeur.
  3. & l'opérateur donne l'adresse d'un emplacement mémoire.

Le reste est composé de sucre syntaxique et de bon sens. Il suffit d’écrire quelques programmes simples en C (comme l’implémentation d’une bibliothèque de listes chaînées) à l’aide de pointeurs.


2
  1. Le pointeur peut être considéré comme une généralisation d'un index dans un tableau.
    • Considérez qu’un grand tableau peut être découpé en un certain nombre de tableaux plus petits, de taille variable, ne se chevauchant pas. Maintenant, ces tableaux plus petits sont ce que nous considérons habituellement comme un tableau. Le plus grand représente alors la totalité de la mémoire de l'ordinateur. Le processus consistant à couper des tableaux plus petits est appelé allocation de mémoire.
  2. Un ensemble de structures reliées entre elles par certains pointeurs peut être considéré comme un graphe dirigé .
    • Chaque sommet est une variable pouvant contenir une valeur.
    • Certaines variables sont des pointeurs et chaque pointeur peut avoir exactement un bord sortant en quelque chose d'autre.
    • Les variables qui ne sont pas des pointeurs n'auront aucun bord sortant. Ils pourraient avoir n'importe quel nombre de bord entrant.

2

Je ne me souviens plus très bien des circonstances entourant mon pointeur-aha-moment, mais j'ai réaménagé la mémoire rétroactivement autour de ma compréhension d'un tableau de style C. (c'est-à arr[3]- dire identique *(arr+3))

Pour une raison quelconque, je trouve extrêmement utile de considérer les pointeurs comme des tableaux chaque fois que je rencontre une situation de pointeur.


2

@Gary Rowe a présenté le bon modèle. La mémoire est un ensemble de boîtes avec des adresses (numéros). Chaque case stocke une valeur (nombre).

L'idée d'un pointeur est d'interpréter la valeur d'une case comme l'adresse d'une autre case. Cette valeur est utilisée pour faire référence à une boîte spécifique, c'est pourquoi on l'appelle une référence . Ainsi, le déréférencement est le processus d'ouverture de la boîte à laquelle il est fait référence.

Si vest une variable (boîte), alors la déclaration

  • vsignifie la valeur de v, c.-à-d. donnez-moi ce qu'il y a dans la boîte
  • *vsignifie déréférencer la valeur de v, c.-à-d. donnez-moi ce qui est dans la case désignée par la valeur dev
  • &vsignifie référence v, c'est-à-dire donnez-moi l'adresse sur la case

Je pense que cela ne vise pas à introduire les pointeurs comme quelque chose de complètement différent. C'était un concept difficile à saisir pour moi quand j'étais enfant. Cela ressemblait toujours à une magie noire que je n'avais jamais vraiment comprise et qui nécessitait beaucoup de caractères spéciaux. La première fois que j'ai compris, c'est quand j'ai écrit un petit jeu utilisant la double indirection dans un langage ne comportant pas d'arithmétique à pointeur. Cela m'a éclairé.

Les pointeurs sont une question d'interprétation. Je pense expliquer cela rend les choses beaucoup plus faciles. Et l'arithmétique de pointeur est une opération extrêmement simple et intuitive si on lui montre un exemple simple avec une mémoire de 10 variables.


2

L'explication que j'ai vraiment critiquée était:

Considérons une grille de ville avec différentes maisons construites sur des terrains. Dans votre main, vous tenez un morceau de papier. Sur le papier que vous avez écrit:


La maison de David,

112 Untel et une rue.


Le morceau de papier (variable du pointeur) contient une adresse qui pointe vers la maison de David. Lorsque vous voulez demander à un ami de jeter un coup d'œil à la maison cool de David, il est beaucoup plus facile d'utiliser le morceau de papier comme référence à la maison que d'envoyer le bâtiment de deux étages par la poste.

Comme avec de véritables pointeurs, vous pouvez avoir des problèmes lorsque vous suivez l'adresse sur votre feuille de papier. David aurait pu bouger et quand vous y arriverez, vous trouverez juste un grand trou dans le sol. Dans ce cas, il aurait été préférable d'effacer l'adresse sur le papier lorsque David l'a déplacée ou au moins de la changer pour la nouvelle. Vous pouvez également constater que vous allez à l'adresse et entrez ce que vous pensez être le salon de votre ami David, mais cette fois-ci, vous vous retrouvez dans une piscine complète pour étrangers. Quelqu'un d'autre a utilisé l'espace à l'adresse que vous aviez pour quelque chose de complètement différent.


2

Si vous voulez expliquer les pointeurs, vous devez d'abord expliquer la mémoire. Je le fais habituellement en utilisant du papier quadrillé / du papier quadrillé avec des lignes et des colonnes. Si "l'étudiant" comprend la mémoire, il peut comprendre ce qu'est une adresse. Si vous avez une adresse, vous avez des pointeurs.

Vous pouvez jouer avec cette abstraction. Par exemple, écrivez l'adresse (numéro) d'un carré dans un autre carré. Maintenant, tracez une flèche du carré du pointeur au carré de destination. Maintenant écrasez le pointeur (par exemple, augmentez-le) et ajustez la flèche. Écrivez une adresse dans un autre carré et laissez l’élève dessiner la flèche ...

Prochaine étape: attribuez un nom à certaines cases (comme le pointeur). Vous pouvez maintenant expliquer le déréférencement. C'est ça.


2
Cela me rappelle un "ordinateur" que j'avais utilisé avant de pouvoir mettre la main sur un ordinateur qui utilisait réellement des électrons - le carton "CARDIAC", je crois, s'appelait. Littéralement, écrivez des nombres dans des boîtes numérotées pour obtenir des numéros d'autres boîtes numérotées. Il était éducatif et je ne ai eu du mal à comprendre des pointeurs sur des microprocesseurs réels.
DarenW

2

Peut-être que c'est juste moi, mais je travaille bien avec des analogies. Supposons donc que vous avez un ami (fonction / classe) "Foo", qui souhaite que quelqu'un d'autre (fonction / classe différente), "Bar", vous contacte pour une raison quelconque. "Foo" pourrait vous amener à aller voir "Bar", mais ce n'est pas pratique, déplacer tous ces êtres (instances). Cependant, "Foo" pourrait envoyer à "Bar" votre numéro de téléphone (pointeur). Ainsi, où que vous soyez, "Foo" saura vous contacter sans avoir à vous trouver.

Et, disons que "Bar" a une connaissance, "Baz", qui souhaite également vous contacter. Mais vous protégez votre numéro de téléphone et vous ne voulez pas que tout le monde l'ait, "Baz" peut appeler "Bar" (le téléphone en tant que pointeur), qui peut ensuite vous transférer l'appel (un autre pointeur). Et ainsi de suite dans la chaîne d'amis de "Baz" et d'amis d'amis.


2

Pointeurs faire façon plus logique si vous avez étudié le langage d'assemblage et / ou de l' architecture informatique. Je pense que si j'enseignais une classe de C, je commencerais par une architecture de quelques semaines pour expliquer le modèle de mémoire et les types d'instructions exécutées par le processeur.


Absolument. Lorsque vous manipulez des registres et comprenez des choses telles que les valeurs immédiates et l'adressage indirect, le concept de pointeur est intuitif. J'ai appris l'assemblage 6502, puis l'assemblage 68K avant d'écrire ma première ligne de C. Ainsi, au moment de me familiariser avec les pointeurs, j'ai examiné l'assemblage (intermédiaire) du compilateur et c'était exactement comme prévu.
Radian

2

Mon "aha!" moment venu dans ce tutoriel:

Tutoriel sur les pointeurs et les tableaux en C

Pour être exact, il est venu dans ce chapitre: Chapitre 3: Pointeurs et chaînes

Pour être encore plus précis, il est venu avec cette phrase:

Le paramètre passé à put () est un pointeur, qui est la valeur d'un pointeur (puisque tous les paramètres en C sont passés par valeur), et la valeur d'un pointeur est l'adresse vers laquelle il pointe, ou simplement une adresse. .

Quand j'ai lu cela, les nuages ​​se sont séparés et les anges ont soufflé des fanfares de trompettes.

Car, voyez-vous, chaque tutoriel ou livre C que j'avais lu auparavant avait affirmé que C pouvait passer par valeur ou par référence, un mensonge néfaste. La vérité est que C passe toujours par valeur, mais parfois, la valeur transmise se trouve être une adresse. Dans la méthode, une copie est faite de cette adresse, tout comme une copie d'un entier transféré. Une copie n'est pas faite de la valeur sur laquelle pointe le pointeur. Ainsi, en utilisant le pointeur dans la méthode, vous pouvez accéder à la valeur d'origine et la modifier.

Je ne suis jamais devenu programmeur C, mais je suis devenu programmeur .NET, et les objets et les références d'objet fonctionnent de la même manière. la référence à l'objet est passée par valeur (et donc copiée), mais l'objet lui-même n'est pas copié. J'ai travaillé avec de nombreux programmeurs qui ne comprennent pas cela parce qu'ils n'ont jamais appris les indicateurs.


1

L'astuce consiste à expliquer que l'emplacement d'une chose et la chose elle-même ne sont pas les mêmes, tout comme l'image d'une pipe n'est pas une pipe . Lorsque vous déplacez une chose, son emplacement change. L'emplacement reste et quelque chose d'autre peut être mis là.


1

Un pointeur est un pense-bête qui vous indique où se trouve quelque chose d’utile. Il contient l'emplacement de la chose et vous indique sa taille (en C, de toute façon). Ainsi, un double pointeur est comme une note autocollante qui dit "Il y a un paquet de six dans le réfrigérateur". Vous devez en fait aller chercher le pack de six pour déterminer s'il s'agit de Coca-Cola ou de Budweiser.


1

Compte tenu du code:

int v=42; // déclaration et initialisation d'une variable simple

int *p = &v; // création d'un point p sur la variable v

Après peut être dit à propos du code ci-dessus:

int * p // "int pointer p" ... voici comment déclarer un pointeur sur une variable de type int

*p // "pointé par p" ... c'est-à-dire les données sur lesquelles p pointe, le même que v.

&v // "adresse de la variable v" ... ceci représente la valeur littérale de p


1

http://cslibrary.stanford.edu/

Ce site propose d'excellents tutoriels pour apprendre les pointeurs et la gestion de la mémoire.

Je vous suggère de parcourir les bases des pointeurs, les pointeurs et la mémoire donnés sur le site. Vous pouvez également consulter les problèmes liés aux listes chaînées indiqués sur le lien pour renforcer davantage les concepts de pointeur.


1

La clé pour expliquer les indicateurs est de s’assurer que les personnes à qui vous expliquez ont déjà compris le concept de mémoire. Ce serait bien s'ils comprenaient vraiment le niveau bas, en croyant que la mémoire existe en tant que tableau volumineux et qu'il est suffisant de comprendre que vous pouvez accéder à n'importe quelle position du tableau par son emplacement d'index.

L’étape suivante, qui consiste à transmettre l’emplacement de l’index plutôt que de copier toute la mémoire, a du sens pour la plupart des gens. Et cela suffit pour permettre à la plupart des gens de comprendre pourquoi les pointeurs sont utiles.

La dernière étape pour comprendre les pointeurs consiste à expliquer comment vous pouvez passer en paramètre un emplacement d’index de mémoire pour que la méthode enregistre l’emplacement d’index où toutes les données sont stockées. J'ai constaté que cela peut aller trop loin pour certaines personnes.

Une fois que quelqu'un a compris ces étapes de base, il est évident qu'il est possible d'enchaîner les pointeurs indéfiniment, aussi longtemps que vous gardez une trace du nombre de fois que vous devez rechercher des adresses pour trouver l'objet de données réel.

Une fois qu'une personne a saisi les pointeurs, elle doit rapidement comprendre la différence entre la mémoire de tas et la mémoire de pile et expliquer pourquoi les pointeurs sur la mémoire de pile sont dangereux lorsqu'ils sont transmis en dehors de la méthode.


0

Je me souviens d'un livre "C puzzles" ou similaire, que j'ai lu uniquement parce que c'était l'un des rares ouvrages sur la programmation / l'informatique disponibles dans la bibliothèque. Ma compréhension de C était rudimentaire. Il a jeté une expression C sur vous et a demandé de l'expliquer, devenant de plus en plus compliqué.


0

Quand j'étais à l'université, mon professeur avait des diapositives PowerPoint vraiment bien nettes décrivant un point comme une variable distincte avec une flèche vers un emplacement de mémoire (représenté par un tableau) et lorsqu'il faisait des listes liées, il le faisait étape par étape -par-étape, indiquant le moment où la flèche change, lorsque le pointeur est déréférencé, etc., il était impossible de ne pas le comprendre en quelques minutes. Le concept lui-même est vraiment facile, mais le faire correctement ou l'appliquer dans des programmes pratiques nécessite plus de pratique.


0

Avant de faire cela, j'explique qu'en programmant, "tout utilise la mémoire" et l'allocation de variables (statiques) en mémoire. Je vais également expliquer ce qu'est une adresse mémoire et la relation entre espace mémoire, adresse mémoire et variables.

Enfin, j’explique qu’il existe des types de données et des variables entières, des données de type chaîne et des variables ... et ainsi de suite, jusqu’à expliquer qu’il existe un type de données spécial qui stocke les adresses mémoire, qui a une valeur vide comme 0 o "", appelé null .

Et, enfin, les variables allouées dynamiquement via l'utilisation de pointeurs.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.