В C, каков правильный синтаксис для объявления указателей? - PullRequest
17 голосов
/ 19 июля 2010

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

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

Type* instance;

Или:

Type *instance;

Хотя я знаю, что оба компилируются в большинстве случаев, я считаю, что есть несколько примеров, где это важно, возможно, связано с объявлением нескольких переменныходного типа в одной строке, и поэтому одно имеет больше смысла, чем другое.

Ответы [ 8 ]

24 голосов
/ 19 июля 2010

Это просто вопрос того, как вам нравится читать.

Причина, по которой некоторые люди говорят так:

Type *instance;

Это потому, что он говорит, что только экземпляр является указателем. Потому что, если у вас есть список переменных:

int* a, b, c;

Только указатель является a, так что проще, чем

int *a, b, c, *d;

Где и a, и d являются указателями. На самом деле это не имеет значения, речь идет только о читабельности.

Другим людям нравится иметь * рядом с типом, потому что (среди прочих причин) они считают его «указателем на целое число» и думают, что * принадлежит типу, а не переменной.

Лично я всегда так делаю

Type *instance;

Но это действительно зависит от вас, а также от правил вашей компании / школьного кодекса.

11 голосов
/ 19 июля 2010

Эти двое одинаковы. Однако, если вы делаете несколько объявлений, первое может вас поймать.

int* pi, j;

объявляет указатель int (pi) и int (j).

7 голосов
/ 19 июля 2010

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

Type (*pointer);

, то есть * всегда привязан к декларатору, а не к спецификатору типа.Если бы вы написали

Type* pointer1, pointer2;

, это было бы проанализировано как

Type (*pointer1), pointer2;

, поэтому в качестве типа указателя будет объявлен только pointer1.

C следует за "объявлением, имитирующим использованиепарадигма;структура объявления должна максимально имитировать эквивалентное выражение, используемое в коде.Например, если у вас есть массив указателей на int с именем arr, и вы хотите получить целочисленное значение, на которое указывает i-й элемент в массиве, вы должны добавить индекс в массив и разыменовать результат, который записанкак *arr[i] (анализируется как *(arr[i])).Типом выражения *arr[i] является int, поэтому объявление для arr записывается как

int *arr[N];

Какой путь вправо ?Зависит от того, кого вы спрашиваете.Старые пуки C, такие как я, предпочитают T *p, потому что они отражают то, что на самом деле происходит в грамматике.Многие программисты на C ++ предпочитают T* p, потому что он подчеркивает тип p, который кажется более естественным во многих обстоятельствах (написав мои собственные типы контейнеров, я вижу смысл, хотя он все еще кажется мне неправильным).

Если вы хотите объявить несколько указателей, вы можете либо объявить их все явно, например:

T *p1, *p2, *p3;

, либо создать typedef:

typedef T *tptr;
tptr p1, p2, p3;

хотя я лично не рекомендую это;сокрытие указателя чего-либо за typedef может укусить вас, если вы не будете осторожны.

3 голосов
/ 19 июля 2010

Эти двое абсолютно одинаковы.

Однако для целей объявления нескольких переменных, как показано ниже:

int * p1, p2;

где p1 имеет указатель типа на int, а p2 имеет тип int. Если вы хотите объявить p2 как указатель на int, вы должны написать:

int *p1, *p2;
2 голосов
/ 19 июля 2010

Я предпочитаю следующий стиль:

Type *pointer;

Почему?Поскольку это согласуется с мышлением, создатели языка пытались установить:

"Синтаксис объявления для переменной имитирует синтаксис выражений, в которых может появиться переменная."

( Язык программирования C Брайана В. Кернигана и Денниса М. Ритчи, версия для с., Стр. 94)

Легко написать ФОРТРАН на любом языкено вы всегда должны писать [язык программирования X] на [языке программирования X].

1 голос
/ 12 апреля 2015

Все они будут скомпилированы, законны и эквивалентны:

Type* instance;
Type * instance;
Type *instance;

Выберите стиль и будьте последовательны.

1 голос
/ 19 июля 2010

Любопытно, что это правило не применяется, если тип выводится в C ++ 0x.

int a;
decltype(&a) i, j;

И i, и j являются int *.

0 голосов
/ 26 февраля 2015

В качестве дополнительного примечания, я думаю, что это помогает понять мотивацию, лежащую в основе синтаксиса объявления C, который предназначен для имитации использования переменной. Некоторые примеры ниже:

  • char *x означает, что если вы сделаете *x, вы получите char.
  • int f(int x) означает, что если вы делаете, например, f(0), вы получите int.
  • const char *foo[3] означает, что если вы делаете, например, *foo[0] (что совпадает с *(foo[0])), вы получаете const char. Это означает, что foo должен быть массивом (в данном случае размером 3) указателей на const char.
  • unsigned int (*foo)[3] означает, что если вы делаете, например, (*foo)[0], вы получите unsigned int. Это означает, что foo должен быть указателем на массив unsigned int (в данном случае размером 3).

В общем, общий синтаксис таков: [what you get] [how you get it]. Хитрость в том, что это может быть расширено до [what you get] [how you get it], [how you get it], ..., чтобы объявить несколько вещей одновременно. Отсюда и следующие три объявления -

int *p;
int f(int x);
int a[3];

- можно объединить в одну строку следующим образом (и да, это даже работает для объявлений функций. Они не являются особенными в этом отношении):

int *p, f(int x), a[3];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...