Все ключевые слова распределены для разделенных запятыми определений переменных? - PullRequest
2 голосов
/ 22 апреля 2019

В выражении типа

static int a, b, c;

применяется static для определения всех трех переменных или только для первой? А как насчет других ключевых слов, таких как volatile или mutable.

Если правило отличается для разных ключевых слов, чем оно отличается?

Например, я знаю, что const распределен, а указатель - нет, например,

int * a, b;

совпадает с

int * a;
int   b;

Примечание: я попытался задать аналогичный вопрос, используя const в качестве примера вместо static, и это было неправильно понято. Хотелось бы узнать, каково правило general для всех применимых ключевых слов в соответствии со стандартом.

Скажем так. Как определение / объявление анализируется в любом случае, когда спецификатор типа переменной состоит из нескольких слов, за которыми следует разделенный запятыми список переменных?

1 Ответ

3 голосов
/ 22 апреля 2019

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

Например:

static int volatile long a, b[10], *&c, *(*const d)(float);
//^^^^^^^^^^^^^^^^^^^^^^
// typey words

//                       ^  ^^^^^  ^^^  ^^^^^^^^^^^^^^^^^^
//                       4 declarators

Здесь

  • a - статическая переменная long int
  • b - статический массив [10] volatile long int
  • c - статическая ссылка на указатель на volatile long int
  • d - staticconst указатель на функцию (с плавающей точкой), возвращающую указатель на volatile long int

(Кроме того, порядок начальных типичных слов не имеет значения.)


Ссылки:

В C ++ 98 (ISO / IEC 14882: 1998) (я знаю, что устарел, но с тех пор эта часть языка принципиально не изменилась) у нас есть (все мои акценты):

In [dcl.dcl] :

simple-объявление:
decl-specier-seq opt init-declarator-list opt
;

[...]

Каждый init-декларатор в init-Заявитель-список содержит ровно один идентификатор объявления , который является именем, объявленным этим init-declarator и, следовательно, одно из имен, объявленных декларацией. спецификаторы типа (7.1.5) в decl-specier-seq и рекурсивная декларатор структура init-декларатора описывает тип (8.3), который затем ассоциируется с именем, объявленным init-декларатором .

(Стандарт предпочитаеттермин «спецификатор объявления» над «типичными словами», но это одно и то же.)

Это говорит о том, что все спецификаторы типа объединяются с каждым декларатором для формирования типа каждого объявленного имени.Спецификаторы типов включают const, volatile, signed, unsigned, а также все основные типы (void, int, wchar_t, ...) и пользовательские class иenum и typedef имена (см. [dcl.type] ).

Подобный язык применяется к спецификаторам классов хранения, которые перечислены отдельно (auto, register,static, extern, mutable) в [dcl.stc] :

  1. [...] хранилищеСпецификатор -class применяется к имени, объявленному каждым init-объявлений в списке , а не к любым именам, объявленным другими спецификаторами.[...]

Аналогично, для typedef имеем (в [dcl.dcl] ):

Если decl-specier-seq содержит спецификатор typedef, объявление называется объявлением typedef и именем каждого инициатора объявления объявляется как typedef-name , синонимично связанному с ним типу (7.1.3).[...]

Позже в главе об объявителях ( [dcl.decl] ) обобщается общий принцип:

Двумя компонентами объявления являются спецификаторы ( decl-specier-seq ; 7.1) и деклараторы ( init-Declarator-list ).Спецификаторы указывают тип, класс хранения или другие свойства объявляемых объектов, функций или typedef.Деклараторы задают имена этих объектов, функций или typedefs и (необязательно) изменяют тип спецификаторов с помощью таких операторов, как * (указатель на) и () (возвращение функции).[...]

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

Эквивалентные участки в текущем черновике:

...