Why does this use of a comma work in an expression, but not in a declaration?

Am from the high-level OOP languages ​​C # and Java, and recently started scratching my head in C. I feel C a bit weird, just like JS feels. Therefore, I want to clarify below:

The following is an error, and it seems intuitive as it looks like the wrong syntax even in OOP languages.

int i=0,1,2; /* Error : expected identifier or '(' before numeric constant int i = 0, 1, 2; ^ */ 

However, the below works surprisingly:

 int i; i = 0,1,2; //works 

Why is this behavior? Do they have any meaning for preserving this behavior or just some technical parsing?

+5
source share
3 answers

This is actually a tricky question because it relies on the details of C's complex grammar. The best source for understanding this is the draft standard , we can use Annex A language syntax summary as a reference.

The basic idea is as follows:

 int i=0,1,2; 

is an announcement and:

 i = 0,1,2; 

- expression.

In an expression, we can have a comma operator that evaluates the left side (usually for side effects), discards the result, and then evaluates the right side, etc.

In a declaration, a comma is a grammatical separator, not a comma operator. , separates declarators, and since 1 and 2 are not declarators in the context of the declaration, this is the wrong syntax:

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

The corresponding 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 

Thus, in this case , separates init declarators, which can be either a declarator or declarator = initializer, neither 1 nor 2 are declarators, so we have the wrong syntax.

There is nothing that an initializer can be an assignment expression, but this expression does not give us a way to the bare comma operator, although we could end with the comma operator in () (through the primary expression) but it will not look like a separator.

For expression, the corresponding grammar from section 6.5.17 :

 expression: assignment-expression expression , assignment-expression 

and the description of the comma operator is as follows:

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

Noting that the comma operator has the lowest priority, the following expression:

 i = 0,1,2; 

is equivalent to:

 (i = 0),1,2; 

and therefore i will get the value 0 , and the results of further evaluations will be deleted.

+7
source
 i = 0,1,2; 

This is an assignment that is equivalent to:

 (i = 0), 1, 2; 

The comma operator (with the lowest priority) evaluates all operands from left to right, first assigns i = 0 , then expression 1 and 2 and deletes the result.

Second example

 int i=0,1,2; 

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

It works if you use:

 int i=(0,1,2); 
+9
source

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 , and then does 0, 1 and 2 . Check out the second example that I mentioned.

In addition, Try i=3;0;1;2; This will not report any error. It just does (i=3), (0), (1) and (2) .

0
source

Source: https://habr.com/ru/post/1205265/


All Articles