Почему 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)
Это также становится трудно читать.
Другие символы могли быть возможными (они @не использовались, пока Objective C не присвоил их ). Хотя опять же, это относится к сути «C использует, *потому что B сделал». Почему B не использовал @? Ну, Б не использовал всех персонажей. Не было никакой bppпрограммы (сравните cpp ), и другие символы были доступны в B (например, #которые позже использовались cpp).
Если я могу рискнуть предположить, почему - это из-за того, где ключи. Из руководства по B :
Чтобы облегчить манипулирование адресами, когда это кажется целесообразным, B предоставляет два оператора унарных адресов, *и &. &является оператором адреса, так же &xкак и адрес x, при условии, что он есть. *является оператором косвенности; *xозначает «использовать содержимое х в качестве адреса».
Обратите внимание, что &это shift-7 и *shift-8. Их близость друг к другу, возможно, была подсказкой программисту о том, что они делают ... но это только предположение. Можно было бы спросить Кена Томпсона о том, почему был сделан этот выбор.
Итак, вот оно. С так, потому что Б было. В это так, потому что он хотел изменить то, как был BCPL.
->он используется на языке C в качестве оператора разыменования - при доступе к полям в struct:,struct_pointer->fieldчто сокращенно(*struct_pointer).field.