The following declaration in C:
int* a, b;
will declare a
as type int*
and b
as type int
There may be an additional historical reason, but I've always understood it this way:
One declaration, one type.
If a, b, c, and d must be the same type here:
int a, b, c, d;
Then everything on the line must an integer as well.
int a, *b, **c, ***d;
The 4 integers:
It may be related to operator precedence, as well, or it may have been at some point in the past.
Consider the declaration:
int *a[10];
int (*b)[10];
The first is an array of ten pointers to integers, the second is a pointer to an array of ten integers.
Now, if the * was attached to the type declaration, it wouldn't be syntatically valid to put a parenthesis between them. So you'd have to find another way to differentiate between the two forms.
C declarations were written this way so that "declaration mirrors use". This is why you declare arrays like this:
int a[10];
Were you to instead have the rule you propose, where it is always
type identifier, identifier, identifier, ... ;
...then arrays would logically have to be declared like this:
int[10] a;
which is fine, but doesn't mirror how you use a
. Note that this holds for functions, too - we declare functions like this:
void foo(int a, char *b);
rather than
void(int a, char* b) foo;
In general, the "declaration mirrors use" rule means that you only have to remember one set of associativity rules, which apply to both operators like *
, []
and ()
when you're using the value, and the corresponding tokens in declarators like *
, []
and ()
.
After some further thought, I think it's also worth pointing out that spelling "pointer to int" as "int*
" is only a consequence of "declaration mirrors use" anyway. If you were going to use another style of declaration, it would probably make more sense to spell "pointer to int" as "&int
", or something completely different like "@int
".
Because if the statement
int* a, b;
were to declare b
as a pointer too, then you would have no way to declare
int* a;
int b;
on a single line.
On the other hand, you can do
int*a, *b;
to get what you want.
Think about it like that: the way it is now it is still the most concise and yet unique way to do it. That's what C is mostly about :)
There's a web page on The Development of the C Language that says, "The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression." Search for that sentence on the page to find the relevant section that talks about this question.
I assume it is related to the full declaration syntax for type modifiers:
int x[20], y;
int (*fp)(), z;
In these examples, it feels much more obvious that the modifiers are only affecting one of the declarations. One guess is that once K&R decided to design modifiers this way, it felt "correct" to have modifiers only affect one declaration.
On a side note, I would recommend just limiting yourself to one variable per declaration:
int *x;
int y;