In C and C++, is an expression using the comma operator like "a = b, ++a;" undefined?
Case 3 is well defined.
First, let's look at how the expression is parsed:
a = b + a, a++
The comma operator ,
has the lowest precedence, followed by the assignment operator =
, the addition operator +
and the postincrement operator ++
. So with the implicit parenthesis it is parsed as:
(a = (b + a)), (a++)
From here, section 6.5.17 of the C standard regarding the comma operator ,
says the following:
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
Section 5.14 p1 of the C++11 standard has similar language:
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded- value expression. Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field.
Because of the sequence point, a = b + a
is guaranteed to be fully evaluated before a++
in the expression a = b + a, a++
.
Regarding free(foo), foo = bar
, this also guarantees that foo
is free'ed before a new value is assigned.
a = b + a, a++;
is well-defined, but a = (b + a, a++);
can be undefined.
First of all, the operator precedence makes the expression equivalent to (a = (b+a)), a++;
, where +
has the highest precedence, followed by =
, followed by ,
. The comma operator includes a sequence point between the evaluation of its left and right operand. So the code is, uninterestingly, completely equivalent to:
a = b + a;
a++;
Which is of course well-defined.
Had we instead written a = (b + a, a++);
, then the sequence point in the comma operator wouldn't save the day. Because then the expression would have been equivalent to
(void)(b + a);
a = a++;
- In C and C++14 or older,
a = a++
is unsequenced , (see C11 6.5.16/3). Meaning this is undefined behavior (Per C11 6.5/2). Note that C++11 and C++14 were badly formulated and ambiguous. - In C++17 or later, the operands of the
=
operator are sequenced right to left and this is still well-defined.
All of this assuming no C++ operator overloading takes place. In that case, the parameters to the overloaded operator function will be evaluated, a sequence point takes place before the function is called, and what happens from there depends on the internals of that function.