Чому C використовує зірочку для покажчиків?
Просто - тому що Б зробив.
Оскільки пам'ять є лінійним масивом, можна інтерпретувати значення в комірці як індекс цього масиву, а BCPL постачає оператор для цієї мети. Мовою оригіналу було написано rv
, і пізніше !
, тоді як B використовує одинарний *
. Таким чином, якщо p
комірка, що містить індекс (або адресу), або покажчик на) іншої комірки, *p
посилається на вміст комірки, що вказує на точку, або як значення в виразі, або як ціль призначення.
Із розвитку мови С
Це воно. На даний момент питання настільки ж нецікаве, як "чому python 3 використовує .
для виклику методу? Чому ні ->
?" Ну ... тому що Python 2 використовує .
для виклику методу.
Рідко мова існує з нічого. Він має вплив і ґрунтується на чомусь, що було раніше.
Отже, чому B не використовував !
для дефренансування вказівника, як це робив його попередник BCPL?
Що ж, BCPL був трохи розмовним. Замість &&
або ||
BCPL використовується logand
і logor
. Це було тому, що більшість клавіатур не мають ∧
або ∨
клавіш, а не однакові були фактично словом NEQV
(див . Посібник з BCPL ).
Здається, B частково надихнувся на посилення синтаксису, а не на довгі слова для всіх цих логічних операторів, що програмісти робили досить часто. І таким чином !
для дереференції стало *
таким, що !
може бути використане для логічного заперечення. Зауважте, є різниця між одинарним *
оператором і двійковим *
оператором (множення).
Ну, а як щодо інших варіантів, як ->
?
->
Було прийнято для синтаксичного цукру навколо поля derefrences struct_pointer->field
який(*struct_pointer).field
Інші варіанти, як-от, <-
можуть створити неоднозначні розбирання. Наприклад:
foo <- bar
Чи слід це читати як:
(foo) <- (bar)
або
(foo) < (-bar)
Створення одинарного оператора, що складається з двійкового оператора та іншого одинарного оператора, цілком ймовірно, матиме проблеми, оскільки другий одинарний оператор може бути префіксом для іншого виразу.
Крім того, знову важливо намагатися зводити речі, які часто вводяться, до мінімуму. Мені б не хотілося писати:
int main(int argc, char->-> argv, char->-> envp)
Це також стає важко читати.
Можливо, можливі й інші символи ( @
не використовувався, поки ціль C не призначила його ). Хоча знову ж таки, це іде до основи «C використовує, *
тому що B». Чому B не використовував @
? Ну, B використовував не всіх персонажів. Не було bpp
програми (порівняти cpp ), а інші символи були доступні в B (такі, #
які пізніше використовували cpp).
Якщо я можу загрожувати здогадкою, чому - це через те, де клавіші. З посібника на B :
Щоб полегшити маніпулювання адресами, коли це здається доцільним, B надає два оператори унарної адреси *
та &
. &
є адресовим оператором, так &x
це адреса x
, якщо припустити, що він є. *
є оператором опосередкування; *x
означає "використовувати вміст x як адресу".
Зауважте, що &
це shift-7 і *
є shift-8. Їх близькість один до одного, можливо, була натяком програмісту на те, що вони роблять ... але це лише здогадки. Варто було б запитати Кена Томпсона про те, чому був зроблений такий вибір.
Отже, там у вас є. C саме так, бо Б був. Це так, тому що він хотів змінитись із того, яким був BCPL.
->
що використовується мовою С як оператор скидання - при доступі до полів у структурі:,struct_pointer->field
що скорочено(*struct_pointer).field
.