Plusieurs pointeurs peuvent-ils référencer la même variable en C ?

3

C’est une bizarrerie du C qui fait souvent trébucher les débutants mais qui semble magique une fois qu’elle clique : vous pouvez avoir une douzaine de pointeurs fixant tous la même adresse mémoire.

Considérez ce scénario. Vous déclarez un entier « i ». Ensuite, vous déclarez trois pointeurs « p », « q » et « r ». Vous les attribuez tous à l’adresse « i ».

Regardez cette dernière ligne. r n’a pas besoin de connaître directement i. Il pointe simplement vers ce vers quoi « p » pointe. Et « p » pointe vers « i ». Donc « r » pointe également vers « i ».

L’opérateur d’affectation copie ici l’adresse, pas la valeur. Lorsque vous faites r = p, vous ne copiez pas l’entier à l’intérieur de i. Vous copiez l’emplacement mémoire détenu par « p ».

Une fois ce code exécuté, « i » a essentiellement quatre noms. Vous pouvez y accéder via « i ». Vous pouvez y accéder via *p. Vous pouvez y accéder via *q. Ou vous pouvez y accéder via *r.

Il n’y a aucune limite technique quant au nombre de pointeurs que vous pouvez empiler ainsi.

Pourquoi c’est important

Il ne s’agit pas seulement d’une syntaxe académique. Cela change votre façon de penser le flux de données.

Dans les langages avec des références d’objet strictes, la copie d’un objet crée souvent une nouvelle instance en mémoire. En C, copier un pointeur est bon marché. C’est juste une adresse mémoire. Rapide. Minuscule.

Cela permet à plusieurs parties de votre code de manipuler les mêmes données sans duplication. Modifiez *p et *q voit le changement immédiatement.

Vous créez des alias pour la mémoire.

Le risque d’alias

C’est ici que « l’aspect cool » devient un handicap.

Si p, q et r pointent tous vers i, n’importe lequel d’entre eux peut modifier i.

Maintenant, « i » vaut 10. « q » vaut 10. « r » vaut 10.

Mais que se passe-t-il si vous oubliez que « r » surveille également « i » ? Vous pourriez supposer que « i » est stable parce que vous ne l’avez pas touché directement. Vous avez seulement touché *q.

C’est une ressource partagée. Et les ressources partagées sont le lieu où vivent les conditions de concurrence et les écrasements inattendus.

Comment prévenir les effets secondaires involontaires

Si vous voulez vous assurer qu’un pointeur n’écrase pas accidentellement les données destinées à un autre, vous utilisez « const ».

Maintenant, « r » peut lire « i ». Cela peut le signaler. Cela ne peut pas le changer.

C’est ainsi que vous imposez des limites dans un langage qui vous fait confiance pour gérer la mémoire manuellement.

Où cela s’intègre-t-il dans la programmation des systèmes

Vous voyez ce modèle partout dans le code système.

Les structures du noyau ont souvent plusieurs pointeurs vers le même bloc de contrôle. Les pilotes de périphérique mappent le même registre matériel à différents noms logiques.

Comprendre que les pointeurs ne sont que des étiquettes pour les adresses vous aide à déboguer ces problèmes. Lorsque la mémoire est corrompue, tracez les pointeurs. Qui d’autre