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` or `unsigned` can be combined with `char`, `long`, `short`,
> >  or `int`.
> > 
> > 
> > — `short` or `long` can be combined with `int`.
> > 
> > 
> > — `long` can be combined with `double`.
> > 
> > 
> > — `long` can be combined with `long`.
> > 
> > 
> > 
> 
> 
> 

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.99
> 
> 
> 99) 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.