Am from high level OOP languages C# and Java and recently started scratching my head in C. I feel C a bit weird as equally as one feels JS is. So want to clarify below:
Below gives error and that seems intuitive as it looks like incorrect syntax even in OOP languages
int i=0,1,2;
/*
Error : expected identifier or ‘(’ before numeric constant
int i = 0, 1, 2;
^
*/
However below works surprisingly:
int i;
i = 0,1,2; //works
Why is this behavior? Is their any significance to keep such behavior or just some parsing technicalities?
This is actually a tricky question because it relies on the details of the C grammar which is complicated. The best source for understanding it is the draft standard, we can use
Annex A
Language syntax summary as a reference.The basic idea is that:
is a declaration and:
is an expression.
In an expression we can have the comma operator which evaluates the left hand side(usually for side effects), throws away the result and then evaluates the right hand side etc...
In declaration the comma is a grammatical separator not the comma operator. The
,
separates declarators and since1
and2
are not declarators in the context of a declaration this is incorrect syntax:The relevant grammar from the C99 standard is as follows:
So in this case the
,
separates init-declarators which can either be a declarator or a declarator = initializer neither1
nor2
are declarators and so we have incorrect syntax.It is worth nothing that an initializer can be an assignment-expression but this expression does not gives us a path to a bare comma operator, although we could end up with a comma operator in
()
(through primary-expression) but this would not look like a separator.For the expression the relevant grammar from section
6.5.17
is:and the description of the comma operator is as follows:
Noting that the comma operator has the lowest precedence the following expression:
is equivalent to:
and so
i
will get the value of0
and the results of the further evaluations are thrown away.This is assignment, which is equivalent to:
The comma operator(which has the lowest precedence) evaluates all operands from left to right, first the assignment
i = 0
, then the expression1
and2
and throws the result away.The second example
is initialization. Compare it with the legal initialization
int i = 0, j = 0;
.It works if you use:
1.
2.
i = 3,0,1,2;
This assigns3 to i
, then executes0, 1 and 2
. Check the 2nd example I mentioned.Also, Try
i=3;0;1;2;
This will not report any error. It will just execute(i=3), (0), (1) and (2)
.