The following is invalid code:
int i = 0, double j = 2.0;
The draft standard says why:
[N4140/7.1.6]
2
As a general rule, at most one type-specifier is allowed in the complete decl-specifier-seq of a declaration or in a type-specifier-seq or trailing-type-specifier-seq. The only exceptions to this rule are the following:—
const
can be combined with any type specifier except itself.—
volatile
can be combined with any type specifier except itself.—
signed
orunsigned
can be combined withchar
,long
,short
, orint
.—
short
orlong
can be combined withint
.—
long
can be combined withdouble
.—
long
can be combined withlong
.
Yes, it prevents something silly like int int
, but I don't see anything wrong with the invalid code posted above. Quoting [N4140/7]
, a simple-declaration consists of a decl-specifier-seqopt init-declarator-listopt;
[N4140/8]
then shows that an init-declarator-list consists of an init-declarator-list , init-declarator,
and an init-declarator is a declarator initializeropt.
Since we're concerned with only syntax of the form int i = 0
, then the declarator we care about is a ptr-declarator, which is a noptr-declarator, which is a declarator-id attribute-specifier-seqopt and finally a declarator-id consists of merely ...
opt id-expression.
For completeness, [N4140/5.1.1]
says an id-expression can be an unqualified-id, or simply an identifier.
If I haven't tripped up so far, this is what the grammar reflects.
int
decl-specifier-seq
i
unqualified-id
= 0
initializer
int i = 0
init-declarator
Since the simple-declaration has the decl-specifier-seq, only one decl-specifier-seq applies to the entire init-declarator-list.
Funnily enough, that means you can't do something like this:
int i, const j;
Yet:
int i, * j;
is perfectly legal because the star is part of a ptr-operator. But you can't do this:
int i, const * j; // pointer to const int
This means in the following code that i
becomes a pointer to const int. Surprise!
int h = 25;
int const * j, * i = &h;
*i = 50; // error: assignment of read-only location '* i'
The intent is clear in [N4140/8]
with:
3
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.9999) A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is
T D1, D2, ... Dn;
is usually equivalent to
T D1; T D2; ... T Dn;
The question is why is it this way?
If it was legal, you could do it in for loops, which is somewhat useful.