Тип декларации - указатель звездочка - PullRequest
32 голосов
/ 24 апреля 2010

в C ++ следующее означает «выделить память для указателя типа int»:

int* number;

Итак, звездочка является частью типа переменной; без него это означало бы «выделить память для int».

Тогда разве не имеет смысла, если следующее означает "выделить память для двух указателей int"?

int* number1, number2;

Ответы [ 5 ]

59 голосов
/ 24 апреля 2010

Страуструпа спросили об этом, и он сказал (перефразируя)

  • если вы думаете больше C-ish, вы скажете int * a и сотрудник * pE (таким образом, вы думаете, что «содержание a является целым числом»)
  • если вы думаете больше о C ++, вы скажете int * a и Employee * pE (так что в вашей голове это " a - целочисленный указатель")

Вы можете думать, как вам нравится, если вы никогда не объявите два указатели на одной строке.

У меня работает. Я человек Employee* pE, но я женат на человеке Employee *pE - мой совет - не слишком переживать по этому поводу.

22 голосов
/ 24 апреля 2010

На самом деле звездочка присоединена к переменной (соглашение, унаследованное от C), поэтому

int * number1, number2;

объявляет number1 как указатель на int (т.е. *number1 является int), а number2 как int.

Интервал не влияет на то, как набираются number. Он просто служит разделителем токенов. Все перечисленное ниже одинаково для компилятора, потому что пробелы будут удалены после разбора.

int *a;
int*a;
int* a;
int * a;
int/**a***/*/*a***/a;

Использование

int* number1, *number2;

чтобы создать два указателя или, что еще лучше, разбить его на несколько объявлений, чтобы избежать путаницы.

int* number1;
int* number2;
18 голосов
/ 24 апреля 2010

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

int *a, *b;

т.е. явно сгруппируйте * s с именами сущностей, а не с именем типа. (Но, в конце концов, это вопрос личных предпочтений.)

Что касается того, почему он разработан таким образом на языке, как вы спрашиваете в одном из комментариев ... Как вы знаете, части синтаксиса объявления, которые описывают тип объявленной сущности, могут появиться на в левой части имени (например, * и &), а также в правой части (например, () и []), как в

int *f(), (&g)[5], h[2][2];

Для битов, которые появляются справа, просто невозможно сделать это любым другим способом. У них нет выбора, кроме как быть сгруппированными по имени сущности, а не по имени типа. Кто-то может спросить, почему вышеупомянутые объявления не делаются в C ++, как

int *() f;
int (&)[5] g;
int [2][2] h;

(т. Е. Все, что связано с типами, появляется в левой части компактной группы) ... Ну, ответ на этот вопрос заключается только в том, как это происходит в C ++. Подход унаследован от C, и там «декларация должна напоминать использование» часто цитируется как обоснование.

P.S. Еще одна вещь, которую следует помнить (и что часто интерпретируется неправильно), заключается в том, что квалификаторы, смежные с именем типа в объявлении, являются частью общего типа , а не частью первого отдельного декларатора. Например

int const *a, *b;

объявляет const int *a и const int *b, а не int *b, как некоторые могут ошибочно полагать. По этой причине я лично предпочитаю использовать более логичный

const int *a, *b;

порядок (хотя в то же время я предпочитаю группировать * с именем, а не с типом).

8 голосов
/ 24 апреля 2010

Это всего лишь одна из многих ошибок синтаксиса объявления Си. Модификатор типа * является частью типа, но синтаксически он принадлежит объявленному идентификатору.
То же самое верно для & и [], кстати.

См. здесь о том, что * делает кроме изменения типа.

3 голосов
/ 24 апреля 2010

Нет,

int* number1, number2;

Объявляет number1 как указатель на int, а number2 как int. Лично я также предпочитаю прикреплять звездочку к типу, который страдает именно той ошибкой, которую вы затронули в этом вопросе, поэтому я бы объявил два указателя следующим образом:

int* number1;
int* number2;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...