Dlaczego C używa gwiazdki do wskaźników?
Po prostu - ponieważ zrobił to B.
Ponieważ pamięć jest tablicą liniową, możliwe jest interpretowanie wartości w komórce jako indeksu w tej tablicy, a BCPL dostarcza operator do tego celu. W oryginalnym języku został napisany rv, a później !, gdy B używa unarnego *. Zatem jeśli pkomórka zawierająca indeks (lub adres) lub wskaźnik do innej komórki, *podnosi się do zawartości wskazanej komórki, albo jako wartość w wyrażeniu, albo jako cel zadania.
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 BCPL logandi logor. Stało się tak, ponieważ większość klawiatur nie ma ∧ani ∨klawiszy, a klucze nie są w rzeczywistości słowem NEQV(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).
A co z innymi opcjami ->?
->Została podjęta na cukier składniowej wokół derefrences polowych struct_pointer->field, które jest(*struct_pointer).field
Inne opcje, takie jak <-mogą tworzyć niejednoznaczne analizy. Na przykład:
foo <- bar
Czy to należy rozumieć jako:
(foo) <- (bar)
lub
(foo) < (-bar)
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ć:
int main(int argc, char->-> argv, char->-> envp)
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ło bppprogramu (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 :
Aby ułatwić manipulowanie adresami, gdy wydaje się to wskazane, B udostępnia dwóch jednoargumentowych operatorów adresów *i &. &jest operatorem adresu, podobnie &xjak adres x, zakładając, że ma jeden. *jest operatorem pośrednim; *xoznacza „użyj zawartości x jako adresu”.
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.
->jest używany w języku C jako operator dereferencji - podczas uzyskiwania dostępu do pól w struct:,struct_pointer->fieldco jest skrótem(*struct_pointer).field.