This is historically grown, and has its roots in the first edition of the K&R in 1978. It has to do with a meaninful order of arguments.
In early C, variables had to be declared at the beginning of a block, following the opening {
and before any other statement in that block (p.81). Having several variables separated by a comma was then presented as convenient way for saving some space when no comment was needed (p.37). (This worry for space nowadays look like a joke, but on a 25 lines x 80 columns standard screen without mouse, it was very useful to be able to verify the variable declarations at the beginning of a function without scrolling too much. Nowadays, variables can be defined just before their usage, so it does not matter so much anymore.)
Function arguments at that time were declared in the argument-list without type, and the types did only follow the declaration of the function (p.67):
int foo(a,b)
int a;
char *s;
{
...
}
It was possible at that time to regroup several arguments of a same type:
int bar(a,b,c)
int a,b,c;
{...}
The only order that mattered was the order of the arguments in the argument list.
Forward declaration of functions and declaration of external functions did not provide the argument list but just ()
. This was very error prone.
So soon after (but not in the original k&R), function prototypes were introduced, to tell the types of the arguments. This looked like:
int foo(int, int, int);
What mattered the most here was the order of the types and not the name of the argument. Note that nowadays, the name of the argument is still optional in prototypes (but not in the function declaration).
The standard committee did a great job in harmonizing the syntax, to come with the usage we nowadays know. And to be consistent between the declaration of the function and the definition of the function requires to have each argument separately introduced with its type.
So in the end, this evolution was driven by the order of the types for parameter passing.
int a, b, c=0
instead ofint a=0, b=0, c=0
, since the first expression pretends to initialize a and b as well with zero, which it does not.