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.
->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.