Właśnie uczę się o C.
Dziwne wydaje mi się to, że twórcy wybrali gwiazdkę ( *
) jako symbol wskaźników zamiast symbolu, który faktycznie wygląda jak wskaźnik ( ->
).
Biorąc pod uwagę, jak mylące mogą być dereferencje i wskaźniki funkcji, czy istnieje historyczny, a nawet praktyczny powód używania gwiazdki?
->
jest używany w języku C jako operator dereferencji - podczas uzyskiwania dostępu do pól w struct:,struct_pointer->field
co jest skrótem(*struct_pointer).field
.structs
dereferencji, co wydawało mi się dziwne. To symbol wskaźnika, prawda? Dlaczego nie (<-
) w przypadku dereferencji? Czy naprawdę jestem jedynym, który myśli w ten sposób?^
jest używany i można go traktować jak obróconą strzałkę i odczytywać jako „wskaż na”, to samo znaczenie,->
ale krótsze.^integer
oznacza „wskaźnik do liczby całkowitej” dla deklaracji typu ivar^
oznacza „pamięćvar
wskazuje na” dla dereferencji. Pozycja symbolu jest bardziej logiczna niż C podczas czytania od lewej do prawej, które zawsze umieszczane są po typie i przed nazwą zmiennej. Pascal używa również@
do pobierania adresu, co jest lepsze niż&
, ponieważ@var
jest to „adres, pod którym znajduje się var”Odpowiedzi:
Po prostu - ponieważ zrobił to B.
Od rozwoju języka C.
To jest to. W tym momencie pytanie jest tak nieciekawe, jak „dlaczego Python 3 używa
.
metody do wywołania metody? Dlaczego nie->
?” Cóż ... ponieważ Python 2 używa.
metody do wywołania metody.Rzadko istnieje język z niczego. Ma wpływ i opiera się na czymś, co było wcześniej.
Dlaczego więc B nie użył
!
do odstresowania wskaźnika, jak jego poprzednik BCPL?Cóż, BCPL było trochę nieporadne. Zamiast
&&
lub||
użyto BCPLlogand
ilogor
. Stało się tak, ponieważ większość klawiatur nie ma∧
ani∨
klawiszy, a klucze nie są w rzeczywistości słowemNEQV
(patrz Podręcznik referencyjny BCPL ).Wygląda na to, że B zostało częściowo zainspirowane raczej do zaostrzenia składni, zamiast mieć długie słowa dla wszystkich tych operatorów logicznych, które programiści robili dość często. I tak
!
stało się dla dereferencji*
, aby!
można było je wykorzystać do logicznej negacji. Zauważ, że istnieje różnica między*
operatorem jednoargumentowym a*
operatorem binarnym (mnożenie).->
Została podjęta na cukier składniowej wokół derefrences polowychstruct_pointer->field
, które jest(*struct_pointer).field
Inne opcje, takie jak
<-
mogą tworzyć niejednoznaczne analizy. Na przykład:Czy to należy rozumieć jako:
lub
Utworzenie jednoargumentowego operatora, który składa się z binarnego operatora i innego jednoargumentowego operatora, może mieć problemy, ponieważ drugi jednoargumentowy operator może być prefiksem innego wyrażenia.
Co więcej, znowu ważne jest, aby często wpisywać rzeczy do minimum. Ja nienawidzę mieć napisać:
To również staje się trudne do odczytania.
Możliwe były inne postacie (
@
nie były używane, dopóki cel C nie przywłaszczył ich ). Chociaż znowu chodzi o sedno „zastosowań C,*
ponieważ B to zrobił”. Dlaczego B nie używał@
? Cóż, B nie użył wszystkich znaków. Nie byłobpp
programu (porównaj cpp ), a inne znaki były dostępne w B (takie jak te,#
które były później używane przez cpp).Jeśli mogę zaryzykować zgadnięcie, dlaczego - to z powodu tego, gdzie są klucze. Z instrukcji na temat B :
Zauważ, że
&
jest to shift-7 i*
shift-8. Ich bliskość mogła być dla programisty wskazówką, co robią ... ale to tylko przypuszczenie. Trzeba by zapytać Kena Thompsona, dlaczego dokonano takiego wyboru.Więc masz to. C jest w ten sposób, ponieważ B był. B jest w ten sposób, ponieważ chciał zmienić z BCPL.
źródło
@
byłaby to inna możliwość.&
i*
). B również nie używał,#
więc było wtedy kilka dodatkowych części ... jest też$
.Student zapytał mnie, czy
&
i*
zostały wybrane, ponieważ były one obok siebie na klawiaturze (coś, czego nigdy wcześniej nie zauważyłem wcześniej). Wiele googlingów doprowadziło mnie do dokumentacji B i BCPL i tego wątku. Jednak w ogóle nie mogłem znaleźć wiele. Wyglądało na to, że*
w B było wiele powodów , ale nie mogłem znaleźć niczego&
.Dlatego zgodnie z sugestią @ MichaelT zapytałem Kena Thompsona:
źródło