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

后端 未结 3 780
独厮守ぢ
独厮守ぢ 2021-01-13 08:48

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:

相关标签:
3条回答
  • 2021-01-13 09:39
    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); 
    
    0 讨论(0)
  • 2021-01-13 09:42

    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).

    0 讨论(0)
  • 2021-01-13 09:43

    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.

    0 讨论(0)
提交回复
热议问题