Is chained assignment in C/C++ undefined behavior?
Asked Answered
M

4

15

Ignoring the types of variables, is expression like a=b=c has defined behavior in both C and C++?

If so, can any one give me official evidence, like quotes from the standard, please?

P.S. I searched the chained assignment but everything I got is associativity, but I didn't find any text about that in the C99 standard. Maybe I did it wrong? hoping anyone can help me.

Matthewmatthews answered 24/3, 2014 at 12:12 Comment(3)
Are we assuming that a, b and c are not the same variable? If they are the same it is more intereting.Sebastiansebastiano
I don't think it warrants any explicit mention in the standards, because an assignment is just an expression which returns the result of the assignment, so a=b=c is equivalent to a=(b=c) and this is no different, in essence, than a=b+c.Knesset
a=b=c hasn't anything with the associativity to do. It will be interpreted as a=(b=c), also b=c;a=(b==0)?1:0 . Sorry, I didn't see qny reason to dig in the standard, it is at the beginning of every c/c++ book.Mckale
E
18

From the C++ Standard

5.17 Assignment and compound assignment operators [expr.ass] 1 The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

And an example from there

int a, b;
a = b = { 1 }; // meaning a=b=1;

From the C Standard

6.5.16 Assignment operators Semantics 3 An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.

As you see there is a difference. In C++ the assignment operator returns an lvalue referring to the left operand while in C it returns the value of the left operand after the assignment,111) but is not an lvalue.

It means that in C++ the following code is valid

int a, b = 20;

( a = 10 ) = b;

while in C the compiler shall issue an error.

Eagle answered 24/3, 2014 at 12:18 Comment(2)
Are all operations in C/C++ grouped from right to left?Matthewmatthews
@Matthewmatthews No they are not. You should read the description of each category of operators. For example expressions with unary operators group right to left while postfix expressions group left to right.Eagle
P
5

According to §6.5.16 (3) of C99:

An assignment expression has the value of the left operand after the assignment, [...]

Together with right-associativity of evaluation, and assuming non-volatile a, b, and c, it means that a = b = c is equivalent to a = (b = c), and again equivalent to b = c; a = b.

Pinpoint answered 24/3, 2014 at 12:21 Comment(2)
I have not found this quite true in practice. Or at least gcc C99 implementation is not up to scratch. a = b = c; looks to be equivalent to b = c; a = c;. Try making b a volatile variable: 'a = b = c;' does not generate read of b. While 'b = c; a = b;' would generate reread of b after write.Duramen
@Duramen Good catch. The answer was written informally to explain the semantics, and assumed local and non-volatile variables where all reads and writes can be reordered or even entirely omitted. I've now made the assumption explicit. Another option would be to describe b = c as _tmp = c; b = _tmp and therefore a = b = c as equivalent to _tmp = c; b = _tmp; a = _tmp, but that seems like sacrificing beginner-level clarity for the sake of expert-level accuracy.Pinpoint
C
2

It C, and C++, assignment is right associative and also an expression, so

a=b=c;

Is treated as:

a=(b=c);

Where the expression b=c evaluates to whatever is in b after the assignment. Note that I say "whatever` as it's possible (but not advisable) in C++ to provide an assigment function that does something other that assignment!

Cycle answered 24/3, 2014 at 12:18 Comment(1)
"Whatever" also matters for C. Unless the value c is representable in the type of b, b=c has value different from c.Grappa
C
1

It is all about associativity. You can rewrite a=b=c as a=(b=c). And the result of an assignment (b=c) is the value of the last assigned variable (b).

Coyote answered 24/3, 2014 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.