Why does this use of comma work in a expression but fail in a declaration?

纵饮孤独 提交于 2019-12-01 06:19:40

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:

int i=0,1,2; 

is a declaration and:

i = 0,1,2; 

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 since 1 and 2 are not declarators in the context of a declaration this is incorrect syntax:

 int i=0,1,2;
        ^^^^

The relevant grammar from the C99 standard is as follows:

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator   <--- here comma is just a seperator
init-declarator:
    declarator
    declarator = initializer

So in this case the , separates init-declarators which can either be a declarator or a declarator = initializer neither 1 nor 2 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:

expression:
    assignment-expression
    expression , assignment-expression

and the description of the comma operator is as follows:

The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value.[...]

Noting that the comma operator has the lowest precedence the following expression:

i = 0,1,2; 

is equivalent to:

(i = 0),1,2; 

and so i will get the value of 0 and the results of the further evaluations are thrown away.

i = 0,1,2; 

This is assignment, which is equivalent to:

(i = 0), 1, 2;

The comma operator(which has the lowest precedence) evaluates all operands from left to right, first the assignment i = 0, then the expression 1 and 2 and throws the result away.

The second example

int i=0,1,2;  

is initialization. Compare it with the legal initialization int i = 0, j = 0;.

It works if you use:

int i=(0,1,2); 

1.

  int i, j;
  i = 3,0,1,2;
  printf("%d\n", i); => prints 3

2.

  i = 3,j =7;
  printf("%d, %d\n", i, j); => prints 3 and 7

i = 3,0,1,2; This assigns 3 to i, then executes 0, 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).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!