Почему синтаксис объявления переменных C ++ несовместим? - PullRequest
13 голосов
/ 01 ноября 2011

когда я объявляю переменные C ++, я делаю это так:

int a,b,c,d;

или

string strA,strB,strC,strD;

Т.е. сначала тип, а затем список имен переменных через запятую.

Тем не менее, я объявляю указатели как это:

int *a,*b,*c,*d;

и ссылки, как это:

int &a,&b,&c,&d;

Чтобы быть последовательным, это должно быть

int* a,b,c,d;

и

int& a,b,c,d;

Почему это не соответствует?

Ответы [ 5 ]

11 голосов
/ 01 ноября 2011

Это из-за наследия Си. Модификатор * применяется к переменной в C. Поэтому разработчики C ++ сделали & для применения к переменной также по аналогии, поскольку они не могли изменить первое без нарушения совместимости с C. То же самое верно и для синтаксиса массива:

int anInt, *aPointerToInt, anArrayOfInt[100];

В Дизайн и развитие C ++ Бьярн Страуструп говорит, что он не был доволен этим, но должен был принять это для совместимости с Си. Он был особенно недоволен этим:

int *a[10];

Из объявления не ясно, является ли a указателем на массив или массив указателей (это массив указателей, для переопределения необходимо использовать скобки).

Конечно, вы всегда можете использовать typedef, чтобы немного почистить вещи.

10 голосов
/ 01 ноября 2011

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

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

Например,

int *a, b;
...
*a = 42;
b = 314159;

... использование a и b выглядит аналогично объявлению a и b.

Есть даже цитата для такого поведения от Денниса Ричи, одного изсоздатели C:

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

  • Деннис Ричи, Развитие языка C . История языков программирования-II изд.Томас Дж. Бергин-младший и Ричард Г. Гибсон-младший ACM Press (Нью-Йорк) и Эддисон-Уэсли (Рединг, Массачусетс) , 1996;ISBN 0-201-89502-1.
7 голосов
/ 01 ноября 2011

Причина в том, что в действительности & и * в C и C ++ относятся к переменной, а no к типу.

Так что проблема в том, что если вы хотите объявить 4 указателя на целые числа, вы должныwrite

int *a, *b, *c, *d;

Writing int* a, b; означает

int *a;
int b;

По этой причине многие люди предпочитают писать int *a;, чем int* a;, просто стиль кода.

Конечно, int* - это тип, но синтаксис C ясно указывает, что в объявлении переменной * и & будут применяться к переменной.

Это происходит по той же причине, что массивы в Cобъявляются следующим образом:

int a[10], b;

std::cout << typeid(a).name() << std::endl; // it will print int[10]
std::cout << typeid(b).name() << std::endl; // it will print int

В других языках, таких как C #, вместо этого используется синтаксис int[] array;.

Другая вещь - это указатель на синтаксис функции:

// Now we declare a variable that is a pointer to function
int (*pt2Function)(char, char) = NULL;

Мы применяем * к имени переменной.

Мне кажется, что использование * и & применяется к переменной, также если 90% из нас предпочтут по-другому, более соответствует остальному языку.

Точно так жеck to arrays:

// Now we declare a variable that is a pointer to an array of 10 integers.
int (*arrayptr)[10];
4 голосов
/ 01 ноября 2011

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

int i;

Использование этой переменной выглядит как i, и это выражение приводит к int.

int *i;

Использование этой переменной выглядит как *i, и это выражение приводит к int. Это также подразумевает, что выражение i приводит к указателю на int.

int i(void);

Использование этой переменной выглядит как i(), и в результате получается int. Это также подразумевает, что i - это функция, которая ничего не берет и возвращает int.

int (*i[5])();

Использование этой переменной выглядит как (*i[x])(), и в результате получается int. Это также означает, что *i[x] - это функция, возвращающая int, i[x] - указатель на функцию, возвращающую int, а i - массив указателей на функции, возвращающие int.

Итак:

int a, *b, c(void), (*d[5])(void);

объявляет несколько выражений, которые имеют тип int, но сами переменные не все int s.

N.B. в объявлениях функций и массивов вложенные объявления буквально не похожи на использование переменной. То есть int i[5]; не означает, что вам нужно заключить '5' в квадратные скобки, когда вы используете i, а int i(int); не означает, что вы вызываете функцию, говоря i(int);. Также объявления переменных структурных типов не соответствуют их использованию, так как вам нужно было бы объявлять выражения для каждой переменной-члена.

С синтаксисом объявления переменных связан синтаксис typedefs. Чтобы объявить typedef с определенным типом, вы используете тот же синтаксис, что и для объявления переменной нужного типа, но вы вставляете typedef перед объявлением, и имя переменной становится именем typedef.

typedef int (*array_of_function_pointers[5])(void);

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

2 голосов
/ 01 ноября 2011

C ++ унаследовал этот синтаксис от C. В книге K & R (§5.1) говорится, что выражение

int *ip, **ipp;

должен быть мнемоническим (то есть вы читали «*ip и **ipp имеют тип int»), они хотели имитировать синтаксис использования.

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

typedef int* intptr;
intptr a, b; // equivalent to: int *a, *b

но на самом деле это никогда не было решением автора C ++, поэтому выбор языка, совместимого с C, подразумевал использование этого синтаксиса, поэтому 1012 *

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