Ниже приведен неверный код:
int i = 0, double j = 2.0;
В проекте стандарта говорится, почему:
[N4140/7.1.6]
2Как правило, не более одного типа-спецификатора допускается в полный decl-specifier-seq декларации или в type-specifier-seq или trailing-type-specifier-seq. Единственными исключениями из этого правила являются следующие:-
constможно комбинировать с любым спецификатором типа, кроме самого себя.-
volatileможно комбинировать с любым спецификатором типа, кроме самого себя.-
signedилиunsignedможно комбинировать сchar,long,short, илиint.-
shortилиlongможно комбинировать сint.-
longможно комбинировать сdouble.-
longможно комбинировать сlong.
Да, это предотвращает что-то глупое как int int, но я не вижу ничего плохого в неверном коде, опубликованном выше. Цитируя [N4140/7], простая декларация состоит из объявления decl-specifier-seq opt init-declarator-list opt;
[N4140/8] показывает, что список init-declarator состоит из init-declarator-list, init-declarator,
а init-declarator - инициализатор декларатора opt.
Поскольку мы имеем дело только с синтаксисом формы int i = 0, то мы должны заботиться о деклараторе ptr-declarator, который является noptr-декларатором, который является атрибутом-атрибутом declarator-id-seq opt, и, наконец, идентификатор declarator состоит только из ... opt id-expression.
Для полноты, [N4140/5.1.1] говорит, что id-выражение может быть неквалифицированным-id или просто идентификатором.
Если я пока не споткнулся, это то, что отражает грамматика.
int decl-specifier-seq
i unqualified-id
= 0 инициализатор
int i = 0 init-declarator
Так как простая декларация имеет spec-specifier-seq, только один spec-specifier-seq применяется ко всему списку init-declarator-list.
Как ни странно, это означает, что вы не можете сделать что-то вроде этого:
int i, const j;
Тем не менее:
int i, * j;
совершенно законно, потому что звезда является частью ptr-оператора. Но вы не можете этого сделать:
int i, const * j; // pointer to const int
Это означает, что в следующем коде i становится указателем на const int. Сюрприз!
int h = 25;
int const * j, * i = &h;
*i = 50; // error: assignment of read-only location '* i'
В [N4140/8] подразумевается намерение:
3Каждый декларатор init в декларации анализируется отдельно как если он был в декларации сам по себе. 9999) Декларация с несколькими деклараторами обычно эквивалентна соответствующая последовательность объявлений, каждая с одной описатель. Это
T D1, D2, ... Dn;обычно эквивалентен
T D1; T D2; ... T Dn;
Вопрос в том, почему это так?
Если это было законно, вы могли бы сделать это для циклов, что несколько полезно.