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

В C, какой правильный синтаксис для объявления указателей?

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

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

Type* instance;

Или:

Type *instance;

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

4b9b3361

Ответ 1

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

Причина, по которой некоторые люди выразились так:

Type *instance;

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

int* a, b, c;

Только a - это указатель, поэтому так проще

int *a, b, c, *d;

Где и a, и d - указатели. Это на самом деле не имеет значения, это просто читаемость.

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

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

Type *instance;

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

Ответ 2

Эти два одинаковые. Однако, если вы выполняете несколько заявлений, первые могут вас поймать.

int* pi, j;

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

Ответ 3

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

Type (*pointer);

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

Type* pointer1, pointer2;

он будет анализироваться как

Type (*pointer1), pointer2;

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

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

int *arr[N];

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

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

T *p1, *p2, *p3;

или вы можете создать typedef:

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

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

Ответ 4

Эти два точно такие же.

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

int * p1, p2;

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

int *p1, *p2;

Ответ 5

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

Type *pointer;

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

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

( Язык программирования C от Brian W. Kernighan и Dennis M. Ritchie, версия ansi c, страница 94)

Легко писать FORTRAN на любом языке, но вы всегда должны писать [язык программирования X] в [языке программирования X].

Ответ 6

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

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

Оба я и j являются int *.

Ответ 7

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

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

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

Ответ 8

Как побочная заметка, я думаю, что это помогает понять мотивацию синтаксиса объявления 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];