Подтвердить что ты не робот

Почему оператор разыменования (*) также используется для объявления указателя?

Я не уверен, что это правильный вопрос программирования, но это то, что меня всегда беспокоило, и мне интересно, не единственный ли я.

Когда я изучал С++, я понял концепцию ссылок, но указатели меня смутили. Почему ты спрашиваешь? Из-за того, как вы объявляете указатель.

Рассмотрим следующее:

void foo(int* bar)
{
}


int main()
{
    int x = 5;
    int* y = NULL;

    y = &x;
    *y = 15;     
    foo(y);

}

Функция foo(int*) принимает в качестве параметра указатель int. Поскольку я объявил y как int указатель, я могу передать y в foo, но когда сначала изучил С++, я связал символ * с разыменованием, поэтому я решил разыменовать int необходимый для передачи. Я попытался бы передать *y в foo, который, очевидно, не работает.

Не было бы проще иметь отдельный оператор для объявления указателя? (или для разыменования). Например:

void test([email protected] x)
{
}
4b9b3361

Ответ 1

В Развитие языка C Деннис Ричи объясняет свои рассуждения таким образом:

Второе нововведение, которое наиболее четко отличает C от его предшественники - это более полная структура типа и особенно ее выражение в синтаксисе объявлений... с учетом объекта любого типа, должно быть возможно описать новый объект, который собирает несколько в массив, выдает его из функции или указатель на это... [Это] привело к синтаксис объявления для имен, дублирующих синтаксис выражения в котором обычно появляются имена. Таким образом,

int i, *pi, **ppi; объявить целое число, указатель на целое число, a указатель на указатель на целое число. Синтаксис этих объявлений отражает, что i, *pi, and **ppi все дают тип intпри использовании в выражении.

Аналогично, int f(), *f(), (*f)(); declare функция, возвращающая целое число, функция, возвращающая указатель на integer, указатель на функцию, возвращающую целое число. int *api[10], (*pai)[10]; объявить массив указателей на целые числа и указатель на массив целых чисел.

Во всех этих случаях декларация переменная напоминает ее использование в выражении, тип которого является одним названный во главе декларации.

Авария синтаксиса способствовала воспринимаемой сложности язык. Оператор косвенности, записанный * в C, синтаксически унарный префиксный оператор, как и в BCPL и B. Это хорошо работает в простые выражения, но в более сложных случаях круглые скобки требуется для направления анализа. Например, чтобы различать косвенность через значение, возвращаемое функцией от вызова функция, обозначенная указателем, записывает *fp() and (*pf)()соответственно. Стиль, используемый в выражениях, объявления, поэтому имена могут быть объявлены

int *fp(); int (*pf)();

В более богатых, но все же реалистичных случаях, все становится хуже: int *(*pfp)(); - указатель на функцию возвращая указатель на целое число.

Возникают два эффекта. Самое главное, C имеет относительно богатый набор способов описания (сравнивается, скажем, с Паскалем). Объявления на языках как например, C-Algol 68, например, описывают объекты одинаково трудно понимаете, просто потому, что сами объекты сложны. второй эффект связан с деталями синтаксиса. Декларации на C должны быть читать в стиле "наизнанку", который многим трудно понять. Sethi [Sethi 81] заметил, что многие из вложенных декларации и выражения станут проще, если косвенность оператор был принят как постфиксный оператор вместо префикса, но к тому времени было уже слишком поздно меняться.

Ответ 2

Причина яснее, если вы пишете это следующим образом:

int x, *y;

То есть, и x, и y являются int. Таким образом, y является int *.

Ответ 3

Это решение языка, которое предшествует С++, поскольку С++ унаследовал его от C. Я когда-то слышал, что мотивация заключалась в том, что объявление и использование были бы эквивалентны, то есть с учетом объявления int *p; выражение *p имеет тип int таким же образом, что при int i; выражение i имеет тип int.

Ответ 4

Поскольку комитет и те, кто разработал С++ за десятилетия до его стандартизации, решили, что * должен сохранить свои исходные три значения:

  • Тип указателя
  • Оператор разыменования
  • Умножение

Вы правы, чтобы предположить, что множественные значения * (и, аналогично, &) запутывают. В течение нескольких лет я придерживался мнения, что это значительный барьер для понимания новичков языка.


Почему бы не выбрать другой символ для С++?

Обратная совместимость является основной причиной... лучше всего использовать существующие символы в новом контексте, чем разрывать программы C, переведя ранее не-операторы в новые значения.


Почему бы не выбрать другой символ для C?

Невозможно знать наверняка, но есть несколько аргументов, которые могут быть — и были? сделал. Прежде всего, идея состоит в том, что:

когда идентификатор [an] появляется в выражении той же формы, что и декларатор, он дает объект указанного типа. {K & R, p216}

Вот почему программисты C стремятся [править] предпочитают выравнивать свои звездочки вправо, а не влево, то есть:

int *ptr1; // roughly C-style
int* ptr2; // roughly C++-style

хотя обе разновидности встречаются в программах обоих языков, изменяясь.

Ответ 5

Страница 65 из Экспертное программирование C: Deep C Secrets включает следующее: И тогда существует философия C, что объявление объекта должно выглядеть как его использование.

Страница 216 of Язык программирования C, второе издание (ака K & R) включает в себя: декларатор читается как утверждение о том, что когда его идентификатор появляется в выражении той же формы, что и декларатор, он дает объект указанного типа.

Я предпочитаю, как это делает ван дер Линден.

Ответ 6

Ха-ха, я чувствую твою боль, у меня была такая же проблема.

Я думал, что указатель должен быть объявлен как &int, потому что имеет смысл, что указатель является адресом чего-то.

Через некоторое время я подумал о себе, каждый тип в C должен быть прочитан назад, например

int * const a

для меня

a constant something, when dereferenced equals an int. То, что должно быть разыменовано, должно быть указателем.