7

I have a simple C code and big confusion about expressions containing comma(,) operator(s).

int main(){
    int i=0,j=11,c;
    c=i=j,++i;
    printf("c=%d i=%d\n",c,i);
    c=(i=j,++i);
    printf("c=%d i=%d\n",c,i);
    return 0;
}

The above code prints:

c=11 i=12
c=12 i=12

My questions are:

  1. What is the actual work of comma(,) as an operator?
  2. ++ has more precedence than , and =, why evaluation is done for the expression on left of comma?
  3. What will be the order if an expression contains operators with different priority, will it depend on comma(,)?
  4. Is it behaving like a substitute of semicolon(;)?
dbc
  • 104,963
  • 20
  • 228
  • 340
skyconfusion
  • 123
  • 8

5 Answers5

10

The assignment operator has a higher priority then the comma operator. Thus expression

c = i = j, ++i;

is equivalent to

( c = i = j ), ++i;

According to the C Standard (6.5.17 Comma operator)

2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)

In the expression above the result of the comma operator is discarded but it has a side effect of increasing i.

In this expression

c = ( i = j, ++i );

due to using parentheses you changed the order of the evaluation of the above expression. Now it is equivalent to

c = ( ( i = j ), ++i );

and variable c gets the value of expression ++i according to the quote from the C Standard listed above.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
4

operator comma is to execute many statement and return only result of last statement.

So for c=i=j,++i; : c=i=j is executed, then ++i and after that result of ++i is returned (but not used).

And for c=(i=j,++i);, according to operator precedence, i=j is executed, and just after ++i is executed, and then affectation to c of result of (i=j, ++i), which is the result of last statement, i.e. ++i

So, the behavior of comma is not really same as semicolon. You can use it as a substitute like in c=i=j,++i;.

Personally, I do not encourage to use this operator, which generates less readable and less maintainable code

Garf365
  • 3,619
  • 5
  • 29
  • 41
2

What is the actual work of comma(,) as an operator?

The comma operator is mainly a superfluous feature. See this for a description of how it works.

++ has more precedence than , and =, why evaluation is done for the expression on left of comma? What will be the order if an expression contains operators with different priority, will it depend on comma(,)?

The left operand is evaluated for side effects. The result of the comma operator is the result of the evaluated right operand. Note that the comma operator has the lowest precedence of all operators in C.

Is it behaving like a substitute of semicolon(;)?

Kind of, yeah. Both a semi-colon and the comma operator includes a sequence point. The difference is that the comma operator isn't the end of a statement, so it can be squeezed in with other operators on the same line, and it also returns a result.

There is really no reason why you ever would want to do this though. The main use of the comma operator is to obfuscate code, it should be avoided. The only reason why you need to learn how it works, is because you might encounter crap code containing it.

For example, your nonsense code should be rewritten into something more readable and safe:

int main(){
    int i=0;
    int j=11;
    int c;

    i=j;
    c=j;
    i++;
    printf("c=%d i=%d\n",c,i);

    i=j;
    i++;
    c=i;
    printf("c=%d i=%d\n",c,i);

    return 0;
}
Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    `// i=j; // superfluous, we already did this, why do it again?` isn't correct as there is an `i++` above, so actually you would end up with `c=11, i=12` followed by `c=13, i=13` – Neil Twist Mar 03 '16 at 11:50
  • @NeilTwist Ah yeah, fixed. – Lundin Mar 03 '16 at 11:55
1

Well let's split it. In the first case c and i take the value of j => c=i=j=11; then you increment i => i=12; So the code is equivalent to this

c = j;
i = j;
++i;

For the second case i takes the value of j => i=j=11 and then you increment i => i=12 and then c takes the value of i => c = 12;

So the code is equivalent to this:

i = j;
++i;
c = i;
asalic
  • 664
  • 3
  • 6
1

The comma operator will evaluate and discard all operations, up to, but not including, the final operation. This allows any number of non-consequential operations to be invoked together on a single line where only the last operation is of interest.

Think of it this way, if you have a number of loop variables to increment at any one location in a loop, you can separate all the additions/subtraction, etc.. over their own individual variables on separate line, but why? Where they are executed (within reason) is of no-consequence to the operation of the code. They then can be invoked on a single line with no adverse effect to the code.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 1
    The comma operator only has 2 operands, so it will simply discard the result of the left operand and use the result of the right one. The right one is always the final one. – Lundin Mar 03 '16 at 09:45
  • "They then can be invoked on a single line with no adverse effect to the code." Nope, they really can't. This code `for (int i=0, int j=0, int k=0; i – Lundin Mar 03 '16 at 09:46
  • 1
    @Lundin Nonsense. Of course you can have more than one loop iterator in a loop. C is not BASIC, and loop iterators don't have a special status; the for loop just has the three horns. Your second example code will go wrong if you want to use `continue`, and it gives `j` and `k` an unnecessarily large scope. – Dan Hulme Mar 03 '16 at 11:59
  • @DanHulme Umm... `continue` is another, unrelated of example of much worse programming practice. Its presence is a certain indication of poor program design and spaghetti programming. You kind of lost all credibility just for bringing that up as something you would like to use. If you want to reduce scope of the variables, then use a function. Loop iterators _do_ have special status, as there is a de facto standard rule saying that for loops should be kept simple, as close to the canonical `for(int i=0; i – Lundin Mar 03 '16 at 12:24
  • All of the above isn't just some personal opinions, it is industry de facto. Check for example MISRA-C, CERT C etc. Also [see this](http://stackoverflow.com/questions/4913981/why-is-continue-inside-a-loop-a-bad-idea). – Lundin Mar 03 '16 at 12:25
  • 1
    Isn't "industry de facto" the same thing as saying it's your opinion? MISRA is applicable to a small subset of C programs; for larger projects it's a huge limit on scalability. – Dan Hulme Mar 03 '16 at 12:48