Perché C usa l'asterisco per i puntatori? [chiuso]


21

Sto solo ora imparando a conoscere C.

Trovo strano che i creatori abbiano scelto l'asterisco ( *) come simbolo per i puntatori piuttosto che un simbolo che in realtà sembra un puntatore ( ->).

Considerando quanto possano essere confusi la dereferenziazione e gli indicatori di funzione, c'è un motivo storico, o anche pratico, per usare l'asterisco?


10
Si noti che ->viene utilizzato nel linguaggio C come operatore di dereference - quando si accede ai campi in una struttura:, struct_pointer->fieldche è l'abbreviazione di (*struct_pointer).field.
amon

@amon: vale solo structsper il dereferenziamento, che mi è sembrato strano. È un simbolo del puntatore, giusto? Perché no ( <-) per la dereferenziazione? Sono davvero l'unico che la pensa così?
Noob Saibot,

1
Date le due eccellenti risposte a questa domanda, tra cui una con una risposta direttamente dal progettista del linguaggio, è difficile giustificare davvero la chiusura come "basata sull'opinione". Ho quindi nominato per la riapertura.
Jules,

Lo stile IMHO Pascal è migliore. ^viene utilizzato e può essere pensato come una freccia ruotata e letto come "punta a", stesso significato di ->ma più breve. ^integersignifica "puntatore a un numero intero" per la dichiarazione del tipo e var^significa "la memoria varpunta a" per la dereferenziazione. La posizione del simbolo è più logica di C quando si legge da sinistra a destra, che mette sempre dopo il tipo e prima del nome della variabile. Pascal usa anche @per prendere l'indirizzo, che è meglio di &, perché @varè "l'indirizzo al quale si trova var"
phuclv

Risposte:


59

Perché C usa l'asterisco per i puntatori?

Semplicemente perché B lo ha fatto.

Poiché la memoria è un array lineare, è possibile interpretare il valore in una cella come un indice in questo array e BCPL fornisce un operatore per questo scopo. Nella lingua originale è stato scritto rv, e successivamente !, mentre B usa l'unario *. Pertanto, se pè una cella che contiene l'indice di (o l'indirizzo di) o il puntatore a) un'altra cella, si *priferisce al contenuto della cella puntata, sia come valore in un'espressione sia come target di un compito.

Dallo sviluppo del linguaggio C.

Questo è tutto. A questo punto, la domanda non è interessante come "perché Python 3 usa .per chiamare un metodo? Perché no ->?" Bene ... perché Python 2 usa .per chiamare un metodo.

Raramente esiste una lingua dal nulla. Ha influenze e si basa su qualcosa che è venuto prima.


Quindi, perché B non ha usato !per derefrittare un puntatore come ha fatto il suo predecessore BCPL?

Bene, BCPL era un po 'prolisso. Invece di &&o ||BCPL usato logande logor. Questo perché la maggior parte delle tastiere non avevano o tasti e non uguali era in realtà la parola NEQV(vedere il Manuale di riferimento BCPL ).

B sembra essere stato parzialmente ispirato a rafforzare la sintassi piuttosto che avere parole lunghe per tutti questi operatori logici che i programmatori hanno fatto abbastanza frequentemente. E così !per la dereferenza divenne *così che !potesse essere usato per negazione logica. Nota che c'è una differenza tra l' *operatore unario e l' *operatore binario (moltiplicazione).


Bene, che dire di altre opzioni, come ->?

Lo è ->stato preso per lo zucchero sintattico attorno alle derefrenze di campo struct_pointer->fieldche è(*struct_pointer).field

Altre opzioni come <-potrebbero creare analisi ambigue. Per esempio:

 foo <- bar

Deve essere letto come:

(foo) <- (bar)

o

(foo) < (-bar)

La creazione di un operatore unario composto da un operatore binario e un altro operatore unario ha probabilmente problemi in quanto il secondo operatore unario può essere un prefisso per un'altra espressione.

Inoltre, è di nuovo importante cercare di ridurre al minimo le cose che vengono digitate frequentemente. Vorrei odio dover scrivere:

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

Anche questo diventa difficile da leggere.

Potrebbero essere stati possibili altri personaggi (il @non è stato usato fino a quando l' obiettivo C non lo si è appropriato ). Anche se, questo va al nocciolo di "C usi *perché B ha fatto". Perché B non l'ha usato @? Bene, B non ha usato tutti i personaggi. Non esisteva un bppprogramma (confronta cpp ) e altri caratteri erano disponibili in B (come quello #che è stato successivamente utilizzato da cpp).

Se posso azzardare un'ipotesi sul perché - è a causa di dove si trovano le chiavi. Da un manuale su B :

Per facilitare la manipolazione degli indirizzi quando sembra opportuno, B fornisce due operatori di indirizzi unari *e &. &è l'operatore di indirizzo così &xè l'indirizzo di x, supponendo che ne abbia uno. *è l'operatore indiretto; *xsignifica "usa il contenuto di x come indirizzo".

Si noti che &è shift-7 ed *è shift-8. La loro vicinanza reciproca potrebbe essere stata un suggerimento per il programmatore su ciò che fanno ... ma è solo una supposizione. Bisognerebbe chiedere a Ken Thompson perché è stata fatta questa scelta.


Così il gioco è fatto. C è così perché B lo era. B è così perché voleva cambiare da come era BCPL.


2
...eccezionale! Questa è un'ottima risposta, @MichaelT! Mi hai mostrato motivi sia storici che pratici, e anche cose che non ho capito bene ma che potevo esaminare. Grazie. +1
Noob Saibot

@NoobSaibot La scelta del personaggio non è tanto un affare quanto il fatto che l'operatore è un operatore prepagato piuttosto che postpendente. Ciò richiede un sacco di parentesi extra (anche se lo zucchero sintattico -> aiuta) che può portare a bug sciocchi ma fastidiosi anche per un programmatore C ++ esperto.
Trixie Wolf,

1
Potresti anche menzionare che C ha trovato un uso per quasi ogni carattere di punteggiatura di Ascii. Non c'erano molti pezzi di ricambio. Immagino che @sarebbe stata un'altra possibilità.
david.pfx,

1
@ david.pfx Mi sono espanso su questo - anche se non era C che ha fatto quella scelta ... era B. E, beh, ho fatto un'ipotesi sul perché (prossimità della tastiera di &e *). Anche B non ha usato, #quindi c'erano ancora alcuni pezzi di ricambio in giro ... c'è anche $.

1
@ david.pfx Il tutorial B che ho trovato è stato scritto da BW Kernighan. Sfortunatamente, Dennis Ritchie non può più essere interrogato (è deceduto nell'ottobre dell'11) mentre Kernighan è apparentemente ancora professore nel dipartimento CS di Princeton. Ken Thompson (l'altro creatore di B) lavora su Google ... Potrebbe anche essersi verificato un problema con alcune tastiere (indicate dalle trigrafi per C per quelli che potremmo pensare come tasti comuni) suggerendo che non tutti erano disponibili ( Non sono sicuro che "@" fosse).

55

Uno studente mi ha chiesto se &e *fosse stato scelto perché si trovavano uno accanto all'altro sulla tastiera (cosa che non avevo mai notato prima). Molto googling mi ha portato alla documentazione B e BCPL, e questo thread. Tuttavia, non sono riuscito a trovare molto. Sembrava che ci fossero molte ragioni per *in B, ma non sono riuscito a trovare nulla per &.

Quindi, seguendo il suggerimento di @ MichaelT, ho chiesto a Ken Thompson:

Da: Ken Thompson <ken@google.com>

vicino sulla tastiera: no.
c copiato da b così & e * sono gli stessi lì.
b ottenuto * da lingue precedenti - alcuni assembly,
bcpl e penso pl / 1.
penso di aver usato e perché il nome (e commerciale)
suona come "indirizzo". b è stato progettato per funzionare con
un teletipo di modello 33 di teletipo. (Codice baud-o a 5 bit),
quindi l'uso dei simboli era limitato.


19
+1 per aver contattato Ken Thompson e aver riportato qui.
stakx,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.