Зачем использовать нотацию * для определения указателя и разыменования?
Есть ли причина, по которой разработчики языка c использовали звезду для определения типа указателя
int* x;
и разыменование указателя?
int y = *x;
Использование одного и того же символа для двух разных вещей кажется странным, тем более что они всегда используются в одном и том же контексте.
1 ответ
Есть отличный ответ на эту тему о Quora Brian. Я воспроизвожу это здесь дословно. http://www.quora.com/C-programming-language/Why-doesnt-C-use-better-notation-for-pointers
Тот факт, что звездочка используется при объявлении указателя, а звездочка используется при разыменовании указателя, - это не некоторый сбой в удобстве использования в Си. Это преднамеренно.
Есть две другие нотации, которые работают так. Вы используете квадратные скобки при объявлении массива, и вы используете квадратные скобки при доступе к массиву. Вы используете круглые скобки при объявлении указателя на функцию, и вы используете круглые скобки при вызове указателя на функцию.
Декларация следует за использованием.
Рассмотрим следующее объявление: int *a; Это объявление говорит вам, что * a имеет тип int. Другими словами, a является указателем на int.
Как насчет этого: int *a[10]; Это объявление говорит вам, что *a[i] (где i находится между 0 и 9 включительно) имеет тип int. Поскольку индексирование массива имеет более высокий приоритет, чем разыменование указателя, это говорит о том, что a - это то, что вы можете использовать [] для (т.е. массив), затем использовать * on (т.е. указатель)... и вы получите int в следствии. Другими словами, a является массивом [10] указателей на int.
int (* a) [10]; Это объявление говорит вам, что (*a)[i] имеет тип int. Поскольку a - это то, что вы можете использовать *, это должен быть указатель. И тогда вы можете использовать [] на результат, чтобы получить int. Итак, мы видим, что тип a должен быть указателем на массив [10] из int.
Обратите внимание, что две вышеуказанные декларации отличаются только в скобках! Но вам не нужно запоминать, куда должны идти скобки для каждого типа, который вы можете объявить. Запишите, как вы будете использовать переменную, и включите последний тип в начале, как в двух приведенных выше примерах. Любые скобки, которые вы должны вставить по причинам старшинства, также включите в декларацию.
Многие программисты на Си не могут вспомнить, как объявлять указатели на функции. Это также становится легким, если вы помните, что объявление следует за использованием. Например, давайте объявим указатель на функцию, который мы можем использовать для хранения адреса функции strcpy. Эта переменная - это то, что для использования вы сначала разыменовываете (с ), затем вызываете, используя (), где круглые скобки содержат два аргумента; первый из них char, а второй const char*. И результат - символ *.
Давайте назовем наш указатель на функцию p. Первое, что мы делаем, это разыменование, поэтому мы записываем *p. Затем мы вызываем p с аргументами char и const char*, поэтому запишите их в скобках рядом с * p: (p) (char, const char *). (Скобки требуются вокруг p, потому что вызов функции имеет более высокий приоритет, чем разыменование.) Наконец, предваряйте результат использования, то есть символ, который возвращает функция. Итак, наша декларация: char * (p) (char, const char *);
const это особый случай. Ключевое слово const в объявлении применяется к тому, что вы бы имели, если бы вы только частично использовали переменную, но остановились, как только вы "добрались" до нее. Это означает, что эту конкретную вещь нельзя изменить.
Теперь я уверен, что вы знаете этот const char *s; объявляет указатель на постоянные символы. Это имеет смысл, так как в начале вещь является const char, т. Е. Результат * s является const char. Тем не менее, вы также можете написать его в виде char const *s;. Интерпретация заключается в том, что мы можем "добраться" до *s, и тогда мы увидим слово const, так что это означает, что до этого момента у нас есть const. Не обращая внимания на const, мы видим char. Так что * s это символ, и это также const, потому что слово const предшествует *s.
А как насчет char *const s;? Это означает постоянный указатель на символ. Указатель не может быть изменен, но то, на что он указывает, может. Это связано с тем, что ключевое слово const идет непосредственно перед s, поэтому оно, так сказать, "лежит на пути" оператора разыменования. s является const до разыменования, но * s не является const. Объявления char const *const s; или const char *const s; означает константный указатель на константный символ
Для двойных (и выше) указателей это одно и то же. const char **p; объявляет указатель на указатель на const char, как и char const **p;. Тем не менее, char *const *p; объявляет указатель на const указатель на char, и char **const p; delcares константный указатель на указатель на символ
Просто помните, что объявление следует за использованием, и вас никогда не смущает синтаксис объявления снова.