Размещение звездочки в объявлениях указателей - PullRequest
78 голосов
/ 08 октября 2008

Я недавно решил, что мне нужно, наконец, выучить C / C ++, и есть одна вещь, которую я не совсем понимаю в отношении указателей или, точнее, их определения.

Как насчет этих примеров:

  1. int* test;
  2. int *test;
  3. int * test;
  4. int* test,test2;
  5. int *test,test2;
  6. int * test,test2;

Теперь, насколько я понимаю, все первые три случая делают одно и то же: Test - это не int, а указатель на один.

Второй набор примеров немного сложнее. В случае 4 и test, и test2 будут указателями на int, тогда как в случае 5 только test является указателем, тогда как test2 - это "реальное" int. Что насчет случая 6? То же, что и в случае 5?

Ответы [ 14 ]

118 голосов
/ 08 октября 2008

4, 5 и 6 - это одно и то же, только test - указатель. Если вы хотите два указателя, вы должны использовать:

int *test, *test2;

Или даже лучше (чтобы все было понятно):

int* test;
int* test2;
42 голосов
/ 08 октября 2008

Пробелы вокруг звездочек не имеют значения. Все три означают одно и то же:

int* test;
int *test;
int * test;

"int *var1, var2" - это злой синтаксис, который просто предназначен для того, чтобы сбить людей с толку и его следует избегать. Расширяется до:

int *var1;
int var2;
32 голосов
/ 08 октября 2008

Используйте "Правило спирали по часовой стрелке" , чтобы помочь разобрать объявления C / C ++;

Существует три простых шага:

  1. Начиная с неизвестного элемента, двигаться по спирали / по часовой стрелке направление; при обнаружении следующих элементов замените их на соответствующие английские высказывания:

    [X] или []: размер массива X ... или размер неопределенного массива ...

    (type1, type2): функции, передающие тип1 и тип2, возвращаются ...

    *: указатель (и) на ...

  2. Продолжайте делать это по спирали / по часовой стрелке, пока все жетоны не будут закрыты.
  3. Всегда сначала разрешайте все в скобках!

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

29 голосов
/ 08 октября 2008

Многие рекомендации по кодированию рекомендуют объявлять только одну переменную в строке . Это позволяет избежать путаницы, которую вы имели до того, как задавать этот вопрос. Большинство программистов на C ++, с которыми я работал, похоже, придерживаются этого.


Я немного знаю, но кое-что, что я нашел полезным, - это чтение деклараций в обратном направлении.

int* test;   // test is a pointer to an int

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

int* const test; // test is a const pointer to an int

int const * test; // test is a pointer to a const int ... but many people write this as  
const int * test; // test is a pointer to an int that's const
12 голосов
/ 31 декабря 2011

Как уже упоминалось, 4, 5 и 6 одинаковы. Часто люди используют эти примеры, чтобы аргументировать, что * принадлежит переменной вместо типа. Хотя это вопрос стиля, есть некоторые споры о том, следует ли вам думать и писать это так:

int* x; // "x is a pointer to int"

или так:

int *x; // "*x is an int"

FWIW Я в первом лагере, но причина, по которой другие приводят аргументы в пользу второй формы, заключается в том, что она (в основном) решает эту конкретную проблему:

int* x,y; // "x is a pointer to int, y is an int"

, что может ввести в заблуждение; вместо этого вы должны написать либо

int *x,y; // it's a little clearer what is going on here

или, если вы действительно хотите два указателя,

int *x, *y; // two pointers

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

11 голосов
/ 15 сентября 2012
#include <type_traits>

std::add_pointer<int>::type test, test2;
5 голосов
/ 08 октября 2008

В 4, 5 и 6 test всегда является указателем, а test2 не указателем. Пробел (почти) никогда не имеет значения в C ++.

1 голос
/ 16 марта 2012

Вы можете думать о 4, 5 и 6 следующим образом: объявление типа должно быть сделано только один раз, но если вы хотите объявить указатель на этот тип (добавив звездочку), вы должны сделать это для каждой переменной.

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

1 голос
/ 08 октября 2008

Указатель является модификатором типа. Лучше читать их справа налево, чтобы лучше понять, как звездочка изменяет тип. 'int *' может читаться как "указатель на int". В нескольких объявлениях вы должны указать, что каждая переменная является указателем или она будет создана как стандартная переменная.

1,2 и 3) Тест относится к типу (int *). Пробелы не имеют значения.

4,5 и 6) Тест относится к типу (int *). Test2 имеет тип int. Опять пробелы несущественны.

0 голосов
/ 02 мая 2019

На мой взгляд, лучше ставить звездочку рядом с именем указателя, а не с типом. Сравните, например ::

int *pointer1, *pointer2; // Fully consistent, two pointers
int* pointer1, pointer2;  // Inconsistent, unexpected, and thus prone to errors

Почему второй случай не согласуется? Потому что, например, int x,y; объявляет две переменные одного типа, но тип упоминается в объявлении только один раз. Это создает прецедент и ожидаемое поведение. И int* pointer1, pointer2; несовместимо с этим.

...