5

I've used SO for a while as a reference, but never asked a question before. I'm currently in a college C++ class and also reading Programming: Principles and Practice by Bjarne Stroutstrup just for my own benifit, as I saw an answer to a question here that really recommended it.

We're covering operators at the moment in my class, and I just can't seem to wrap my head around how the comma operator works in a statement. One example is a sample question for the online portion of the class that I keep getting wrong, even if I write a C program and use GDB to get the result. The question is:

Assuming x==16 before the following expression, what is the value of the following expression (not necessarily the value of x)?

x++, ++x, x+=x

I'm not interested in the correct answer so much as how to get the correct answer. I've read through a couple answers to similar questions, such as this one here, but it seems like I'm missing how this applies when there is actually no assigment operator. Is this the same as saying

int y = (x++, ++x, x+=x);

or

int y = x++, ++x, x+=x;

or neither? Could someone please explain how the comma operator works, specifically in relation to a statement without an assignment?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Joseph Morgan
  • 210
  • 2
  • 8

2 Answers2

8

The comma operator is easy — so easy it is hard. It has the lowest priority of all operators; its priority is even lower than the assignment operators. Note that arguments to functions are not separated by the comma operator.

The comma operator evaluates its left-hand operand, generates a sequence point and discards the result, and then evaluates the right-hand operand.

In context:

x++, ++x, x += x;

is equivalent to:

x++;
++x;
x += x;

except that the overall value is the result of x += x;.

Given that x starts at 16, it is incremented to 17, then 18, then doubled to 36. The overall value is therefore 36.

Note that because of the sequence points, it does not run foul of the rules about not incrementing the same variable more than once between sequence points.

The only reason for using a comma operator really is that there are contexts where you can't use separate statements but you can use comma operators. For example:

for (i = 0, j = n; i < j; ++i, --j)

You can't use semicolons in place of those commas.


In the question, there are two samples:

int y = (x++, ++x, x+=x);

int y = x++, ++x, x+=x;

The first is legitimate (though unnecessarily contorted), and initializes y to 36 (and sets x to 36).

The second is not legitimate and won't compile; the commas are not comma operators and should be separating distinct declarators, but the ++x and x += x are not declarators. However, if it was changed to:

y = x++, ++x, x+=x;

then it would be legitimate. The first term is:

y = x++

which assigns 16 to y and increments x to 17. The second term increments x to 18; the third term changes x to 36.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    [Klas Lindbäck](http://stackoverflow.com/users/646887/klas-lindb%c3%a4ck) — thanks for your edit; I was part way through adding the material after the rule when you made your change. I hope my explanation is at least as good as yours. I already noted at the very top of the answer that the comma operator has even lower precedence than assignment. – Jonathan Leffler Feb 09 '15 at 08:23
4

The comma operator evaluates the first operand, discards it, and then evaluates to the second one, with a sequence point between the evaluations.

In your case it means you have this sequence of expressions evaluated

x++   // evaluates to 16, increments x to 17
++x   // increments x to 18, evaluates to 18
x+=x  // increments x by x, i.e. by 18, evaluates to 36.

And the full expression evaluates to the third sub-expression. The first expression evaluates to 16 but increments x to 17. The second one increments x to 18 and evaluates to that number. The third one increments x by its value of 18, and evaluates to x, that is, evaluating to 36.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480