Pourquoi C utilise-t-il l'astérisque pour les pointeurs? [fermé]


21

J'apprends juste à propos de C.

Je trouve étrange que les créateurs aient choisi l'astérisque ( *) comme symbole pour les pointeurs plutôt qu'un symbole qui ressemble en fait à un pointeur ( ->).

Compte tenu de la confusion possible entre le déréférencement et les pointeurs de fonction, existe-t-il une raison historique, voire pratique, d'utiliser l'astérisque?


10
Notez qu'il ->est utilisé dans le langage C comme opérateur de déréférence - lors de l'accès aux champs dans une structure:, struct_pointer->fieldqui est l'abréviation de (*struct_pointer).field.
amon

@amon: Cela ne concerne structsque le déréférencement, ce qui m'a paru étrange. C'est un symbole de pointeur, non? Pourquoi pas ( <-) pour le déréférencement? Suis-je vraiment le seul à penser de cette façon?
Noob Saibot

1
Compte tenu des deux excellentes réponses à cette question, dont une avec une réponse directement du concepteur de langage, il est difficile de vraiment justifier la clôture comme "basée sur l'opinion". J'ai donc proposé ma réouverture.
Jules

Le style IMHO Pascal est meilleur. ^est utilisé et peut être considéré comme une flèche pivotée et lu comme "pointer vers", même sens ->mais plus court. ^integersignifie "pointeur vers un entier" pour la déclaration de type et var^signifie "la mémoire varpointe vers" pour le déréférencement. La position du symbole est plus logique que C lors de la lecture de gauche à droite, ce qui met toujours après le type et avant le nom de la variable. Pascal utilise également @pour prendre l'adresse, ce qui est mieux que &, car @varc'est "l'adresse à laquelle se trouve var"
phuclv

Réponses:


59

Pourquoi C utilise-t-il l'astérisque pour les pointeurs?

Tout simplement - parce que B l'a fait.

La mémoire étant un tableau linéaire, il est possible d'interpréter la valeur d'une cellule comme un index dans ce tableau et BCPL fournit un opérateur à cet effet. Dans la langue d'origine, il était orthographié rv, et plus tard !, tandis que B utilise l'unaire *. Ainsi, si pest une cellule contenant l'index (ou l'adresse de), ou un pointeur vers) une autre cellule, *pfait référence au contenu de la cellule pointée, soit comme valeur dans une expression, soit comme cible d'une affectation.

Du développement du langage C

C'est ça. À ce stade, la question est aussi inintéressante que "pourquoi python 3 utilise-t-il .pour appeler une méthode? Pourquoi pas ->?" Eh bien ... parce que Python 2 utilise .pour appeler une méthode.

Il existe rarement une langue à partir de rien. Il a des influences et est basé sur quelque chose qui a précédé.


Alors, pourquoi B n'a-t-il pas utilisé !pour déréfrencier un pointeur comme son prédécesseur BCPL?

Eh bien, BCPL était un peu verbeux. Au lieu de &&ou ||BCPL utilisé logandet logor. En effet, la plupart des claviers ne disposent pas de touches ou et ce n'est pas égal au mot NEQV(voir le manuel de référence BCPL ).

B semble avoir été partiellement inspiré pour resserrer la syntaxe plutôt que d'avoir des mots longs pour tous ces opérateurs logiques que les programmeurs ont fait assez fréquemment. Et c'est ainsi !que la déréférence est devenue *ce qui !pourrait être utilisé pour la négation logique. Notez qu'il y a une différence entre l' *opérateur unaire et l' *opérateur binaire (multiplication).


Et les autres options, comme ->?

Le a ->été pris pour le sucre syntaxique autour des déréfrences de champ struct_pointer->fieldqui est(*struct_pointer).field

D'autres options comme <-pourraient créer des analyses ambiguës. Par exemple:

 foo <- bar

Est-ce à lire comme suit:

(foo) <- (bar)

ou

(foo) < (-bar)

La création d'un opérateur unaire composé d'un opérateur binaire et d'un autre opérateur unaire risque fort d'avoir des problèmes car le deuxième opérateur unaire peut être un préfixe pour une autre expression.

De plus, il est encore important d'essayer de réduire au minimum les éléments tapés fréquemment. Je détesterais devoir écrire:

int main(int argc, char->-> argv, char->-> envp)

Cela devient également difficile à lire.

D'autres personnages auraient pu être possibles (le @n'a pas été utilisé avant que l' Objectif C ne s'en soit approprié ). Encore une fois, cela va au cœur de «C utilise *parce que B l'a fait». Pourquoi B n'a-t-il pas utilisé @? Eh bien, B n'a pas utilisé tous les personnages. Il n'y avait pas de bppprogramme (comparer cpp ) et d'autres caractères étaient disponibles en B (comme celui #qui a ensuite été utilisé par cpp).

Si je peux me permettre de deviner pourquoi - c'est à cause de l'emplacement des clés. D'un manuel sur B :

Pour faciliter la manipulation des adresses quand cela semble souhaitable, B fournit deux opérateurs d'adresses unaires, *et &. &est l'opérateur d'adresse tout &xcomme l'adresse de x, en supposant qu'il en ait un. *est l'opérateur d'indirection; *xsignifie "utiliser le contenu de x comme adresse".

Notez que &c'est shift-7 et *c'est shift-8. Leur proximité les uns avec les autres a peut-être été une indication pour le programmeur de ce qu'ils font ... mais ce n'est qu'une supposition. Il faudrait demander à Ken Thompson pourquoi ce choix a été fait.


Alors voilà. C est ainsi parce que B l'était. B est comme ça parce qu'il voulait changer de la façon dont BCPL était.


2
...impressionnant! Ceci est une excellente réponse, @MichaelT! Vous m'avez montré des raisons à la fois historiques et pratiques, et même des choses que je ne comprenais pas très bien mais que je pouvais examiner. Merci. +1
Noob Saibot

@NoobSaibot Le choix du personnage n'est pas autant une affaire que le fait que l'opérateur est un opérateur de préfixe plutôt que de post-paiement. Cela nécessite beaucoup de parens supplémentaires (bien que le sucre syntaxique -> aide), ce qui peut conduire à des bogues stupides mais vexants même pour un programmeur C ++ expérimenté.
Trixie Wolf

1
Vous pourriez également mentionner que C a trouvé une utilisation pour presque tous les caractères de ponctuation Ascii. Il n'y avait pas beaucoup de pièces de rechange. Je suppose que @cela aurait été une autre possibilité.
david.pfx

1
@ david.pfx Je l'ai développé - bien que ce ne soit pas C qui ait fait ce choix ... c'était B. Et, eh bien, j'ai fait une supposition quant à la raison (proximité du clavier de &et *). B n'a pas non plus utilisé, #donc il y avait encore quelques pièces de rechange à ce moment-là ... il y en a aussi $.

1
@ david.pfx Le tutoriel B que j'ai trouvé a été écrit par BW Kernighan. Malheureusement, Dennis Ritchie ne peut plus être interrogé (il est décédé en octobre 2011) tandis que Kernighan est apparemment toujours professeur au département CS de Princeton. Ken Thompson (l'autre créateur de B) travaille chez Google ... Il peut également y avoir eu un problème avec certains claviers (indiqués par les trigraphes pour C pour ce que nous pourrions considérer comme des clés communes) suggérant que tous n'étaient pas disponibles ( Je ne sais pas si «@» l'était).

55

Un étudiant m'a demandé si &et *avait été choisi parce qu'ils étaient côte à côte sur le clavier (quelque chose que je n'avais jamais remarqué auparavant). Beaucoup de recherches sur Google m'ont conduit à la documentation B et BCPL, et à ce fil. Cependant, je n'ai pas pu trouver grand chose du tout. Il semblait qu'il y avait beaucoup de raisons pour *B, mais je n'ai rien trouvé pour &.

Donc, suivant la suggestion de @ MichaelT, j'ai demandé à Ken Thompson:

De: Ken Thompson <ken@google.com>

près du clavier: non.
c copié de b donc & et * y sont les mêmes.
b obtenu * à partir de langues antérieures - certains assemblage,
bcpl et je pense pl / 1.
je pense que j'ai utilisé & parce que le nom (esperluette)
sonne comme "adresse". b a été conçu pour fonctionner avec
un télétype de type 33. (Code baud-o 5 bits)
, l'utilisation des symboles a donc été restreinte.


19
+1 pour avoir contacté Ken Thompson et avoir fait un rapport ici.
stakx
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.