J'ai eu le plaisir récent d'expliquer des pointeurs à un débutant en programmation C et je suis tombé sur la difficulté suivante. Cela peut ne pas sembler un problème du tout si vous savez déjà comment utiliser les pointeurs, mais essayez de regarder l'exemple suivant avec un esprit clair:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
Pour le débutant absolu, le résultat peut être surprenant. À la ligne 2, il venait de déclarer que * bar était & foo, mais à la ligne 4, il s'avère que * bar est en fait foo au lieu de & foo!
La confusion, pourrait-on dire, provient de l'ambiguïté du symbole *: à la ligne 2, il est utilisé pour déclarer un pointeur. À la ligne 4, il est utilisé comme un opérateur unaire qui récupère la valeur sur laquelle pointe le pointeur. Deux choses différentes, non?
Cependant, cette «explication» n'aide pas du tout un débutant. Il introduit un nouveau concept en signalant une différence subtile. Cela ne peut pas être la bonne façon de l'enseigner.
Alors, comment Kernighan et Ritchie l'ont-ils expliqué?
L'opérateur unaire * est l'opérateur d'indirection ou de déréférencement; lorsqu'il est appliqué à un pointeur, il accède à l'objet vers lequel pointe le pointeur. […]
La déclaration du pointeur ip,
int *ip
est conçue comme un mnémonique; il dit que l'expression*ip
est un int. La syntaxe de la déclaration d'une variable imite la syntaxe des expressions dans lesquelles la variable peut apparaître .
int *ip
devrait être lu comme " *ip
retournera un int
"? Mais pourquoi alors l'affectation après la déclaration ne suit-elle pas ce modèle? Que faire si un débutant souhaite initialiser la variable? int *ip = 1
(lire: *ip
renverra un int
et le int
est 1
) ne fonctionnera pas comme prévu. Le modèle conceptuel ne semble tout simplement pas cohérent. Est-ce que j'ai râté quelque chose?
Edit: Il a essayé de résumer les réponses ici .
*
dans une déclaration il y a un jeton signifiant "déclarer un pointeur", dans les expressions c'est l'opérateur de déréférencement, et que ces deux représentent des choses différentes qui se trouvent avoir le même symbole (identique à l'opérateur de multiplication - même symbole, signification différente). C'est déroutant, mais tout ce qui est différent de l'état actuel des choses va être encore pire.
int* bar
rend plus évident que l'étoile fait en fait partie du type, pas de l'identifiant. Bien sûr, cela vous pose différents problèmes avec des trucs peu intuitifs comme int* a, b
.
*
peut avoir deux significations différentes selon le contexte. Tout comme la même lettre peut être prononcée différemment selon le mot dans lequel elle se trouve, il est donc difficile d'apprendre à parler plusieurs langues. Si chaque concept / opération avait son propre symbole, nous aurions besoin de claviers beaucoup plus grands, donc les symboles sont recyclés quand cela a du sens de le faire.
int* p
), tout en avertissant votre élève de ne pas utiliser plusieurs déclarations dans la même ligne lorsque des pointeurs sont impliqués. Lorsque l'élève a complètement compris le concept des pointeurs, expliquez à l'élève que la int *p
syntaxe est est équivalente, puis expliquez le problème avec plusieurs déclarations.