Почему считается, что 'T * name' - путь C, а 'T * name' - путь C ++? - PullRequest
17 голосов
/ 23 июня 2011

Примечание. Этот вопрос касается положения звездочки (*).

В большинстве кодов C, которые я вижу (например, в Руководство Биджа по сетевому программированию ), всеобъявления / определения переменных используют формат T *name, то есть привязывают * к имени переменной.Считается, что указатель относится к переменной, а не к типу.

В большинстве кодов C ++, которые я вижу, формат T* name, то есть он связывает * с типом переменной.Указатель считается принадлежащим типу, а не переменной.Я сам как чистый кодер C ++ также использую этот формат, поскольку указатель на тип явно (для меня) относится к типу, а не к переменной.(Кстати, даже стандарт C ++ использует этот формат в примерах. :))

Есть ли (историческая) причина для этого?Изменился ли образ мышления, когда программисты начали делать C ++?

Было бы также неплохо, если бы кодер C (который использует первый формат) мог объяснить, почему он использует его, а не последний.

Ответы [ 10 ]

23 голосов
/ 23 июня 2011

Если бы я рискнул предположить, я бы сказал, что это связано с тем, что люди на C ++ с большей вероятностью считают информацию о типах чем-то само по себе, потому что шаблоны позволяют программно манипулировать типами во время компиляции.Они также с гораздо меньшей вероятностью объявляют несколько переменных в одном объявлении.

Стиль T* фокусирует информацию о типе в одном месте и выделяет ее, а также путаницу, которая может возникнуть из-за чего-то вроде T* foo, bar; с этим синтаксисом не проблема, если вы никогда не объявляете две переменные в одном выражении.

Лично я нахожу стиль T* очень неприятным и очень ему не нравится.* является частью информации о типе, это правда, но то, как компилятор анализирует его, делает его фактически привязанным к имени, а не к типу.Я думаю, что способ T* скрывает что-то важное, что происходит.

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

Для ясности, конечно, любой стиль работает на любом языке.Но я замечаю то же, что и вы, что один стиль имеет тенденцию быть немного более распространенным в коде C, а другой - чуть более распространенным в C ++.

16 голосов
/ 23 июня 2011

Из Часто задаваемые вопросы о стиле и методике Страуструпа для C ++ .

"Типичный программист на C" пишет int *p; и объясняет это "*p - это то, что int"подчеркивает синтаксис и может указывать на грамматику объявления C (и C ++), чтобы аргументировать правильность стиля.Действительно, * связывается с именем p в грамматике.

«Типичный программист на C ++» пишет int* p; и объясняет это «p - указатель на тип подчеркивания int».На самом деле тип p равен int*.Я явно предпочитаю этот акцент и считаю его важным для хорошего использования более продвинутых частей C ++.

14 голосов
/ 23 июня 2011

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

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

T a, b, c;

относительно часто, в то время как в C ++ это происходит редко.(В C ++ вы объявляете переменные рядом с тем местом, где они используются, а переменные часто имеют параметры конструктора и т. Д .; поэтому редко объявлять несколько объектов в одной строке)

Это также бывает единственным случаем, когдасинтаксис имеет значение, потому что оператор

T* a, b, c;

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

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

Тем не менее, я никогда не видел никаких доказательств этого - этопросто догадка.

12 голосов
/ 23 июня 2011

Несколько человек упомянули очень хорошие моменты.Я просто хочу отметить, что, хотя C очень сильно сохранил значение «объявление отражает использование», C ++ этого не сделал.Некоторые деклараторы в C ++ не отражают использование в объявлениях;

int &ref; // but "&ref" has type "int*", not "int".
int &&ref; // but "&&ref" is not valid at all.

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

9 голосов
/ 23 июня 2011

Причина, по которой программисты на C склонны использовать один стиль, в то время как программисты на C ++ используют другой стиль, довольно проста: Kernighan & Ritchie использовали «стиль C» в своей книге , а Страуструп использовал «стиль C ++». "в его книга .

6 голосов
/ 23 июня 2011

В K & R они используют нотацию type *name, так что, возможно, именно это получили многие программисты на Си.

5 голосов
/ 23 июня 2011

Поскольку у Бьярне было преимущество задним числом: он понял, что синтаксис объявления C был «экспериментом, который не удался» (читай: синтаксис объявления C замедлен)Остальным уже ответили другие.

2 голосов
/ 23 июня 2011

Просто, чтобы бросить спор в дело:

  • Пользователи C ++ обычно заявляют, что одно объявление на строку позволяет поставить звездочку на тип (слева). int* a; int* b;
  • И C, и C ++ анализируются со звездочкой, прикрепленной к имени (справа). int *a;
  • Препроцессоры C ++ часто перемещают звездочку влево. С препроцессорами передвиньте его вправо.
  • На любом языке размещение его слева будет выглядеть странно для объявления нескольких переменных одного типа в одном выражении. int* a, * b, * c;
  • Есть некоторые синтаксические элементы, которые выглядят глупо с левой стороны. int* (* func)().

Существуют и другие неправильно используемые элементы C, такие как const, который тоже принадлежит справа! int const a;. Обычно это ставится слева от типа, несмотря на принадлежность к типу слева от него . Многие компиляторы должны быть изменены для обработки этого использования. В C ++ вы можете заметить, что это соответствует константным методам, поскольку компилятор не может вывести вас, если он указан слева: int A::a() const Это также ломает с вложенным использованием const, restricted и дружит с такими объявлениями как int const *. Обычное использование const предполагает, что это постоянный указатель на целое число, но на самом деле это int *const.

ТЛ; др

Вы все делали все это неправильно, все исправляете.

2 голосов
/ 23 июня 2011

Я не думаю, что вы правы относительно своего различия,

Есть код C ++ в стиле T *.

Есть код C 1009 * в стиле T*.

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

1 голос
/ 23 июня 2011

Объявления C следуют тем же правилам (например, приоритет), что и выражения.На самом деле, совершенно справедливо считать объявление типа

int *foo;

объявлением типа выражения *foo (т. Е. Оператор косвенности, примененный к foo) как int вместо fooкак имеющий тип int*.

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

int* foo;
...