Is comma operator free from side effect?
Asked Answered
D

5

7

For example for such statement:

c += 2, c -= 1

Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?

Dairen answered 16/10, 2011 at 14:5 Comment(3)
What borders me about this question is the "side effect" thing. Does OP want to know something else besides what he actually asked?Lieu
Note: The commas that separate parameters in a function call are NOT the comma operator. So be careful. I have not seen a coding standard that allows comma operators anywhere (apart from inside a for(;;)) and they are generally discouraged in favor of statements which are clearer.Razzledazzle
@TomalakGeret'kal "bother", sorry. To late to edit.Lieu
F
9

Yes, it is guaranteed by the standard, as long as that comma is a non-overloaded comma operator. Quoting n3290 §5.18:

The comma operator groups left-to-right.

expression:
assignment-expression
expression , assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded- value expression (Clause 5)83. 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.

And the corresponding footnote:

83 However, an invocation of an overloaded comma operator is an ordinary function call; hence, the evaluations of its argument expressions are unsequenced relative to one another (see 1.9).

So this holds only for the non-overloaded comma operator.

The , between arguments to a function are not comma operators. This rule does not apply there either.

For C++03, the situation is similar:

The comma operator groups left-to-right.

expression:
assignment-expression
expression , assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is discarded. The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conver- sions are not applied to the left expression. All side effects (1.9) of the left expression, except for the destruction of temporaries (12.2), are performed before the evaluation of the right expression. The type and value of the result are the type and value of the right operand; the result is an lvalue if its right operand is.

Restrictions are the same though: does not apply to overloaded comma operators, or function argument lists.

Fishtail answered 16/10, 2011 at 14:11 Comment(2)
I think there's possibly a subtle "gotcha" here depending on what type c is. If it has operator, overloaded then I think it's not a sequence point and as such could lead to undefined behaviour.Theophrastus
Quite right, I had failed to include that important footnote.Fishtail
A
7

Yes, the comma operator guarantees that the statements are evaluated in left-to-right order, and the returned value is the evaluated rightmost statement.

Be aware, however, that the comma in some contexts is not the comma operator. For example, the above is not guaranteed for function argument lists.

Appall answered 16/10, 2011 at 14:8 Comment(0)
L
4

Yes, in C++ the comma operator is a sequence point and those expression will be evaluated in the order they are written. See 5.18 in the current working draft:

[snip] is evaluated left-to-right. [snip]

I feel that your question is lacking some explanation as to what you mean by "side effects". Every statement in C++ is allowed to have a side effect and so is an overloaded comma operator.

Why is the statement you have written not valid in a function call?

It's all about sequence points. In C++ and C it is forbidden to modify a value twice inside between two sequence points. If your example truly uses operator, every self-assignment is inside its own sequence point. If you use it like this foo(c += 2, c -= 2) the order of evaluation is undefined. I'm actually unsure if the second case is undefined behaviour as I do not know if an argument list is one or many sequence points. I ought to ask a question about this.

Lieu answered 16/10, 2011 at 14:8 Comment(0)
G
1

It should be always evaluated from left to right, as this is the in the definition of the comma operator: Link

Gustavo answered 16/10, 2011 at 14:9 Comment(0)
K
0

You've got two questions.

The first question: "Is comma operator free from side effect?"

The answer to this is no. The comma operator naturally facilitates writing expressions with side effects, and deliberately writing expressions with side effects is what the operator is commonly used for. E.g., in while (cin >> str, str != "exit") the state of the input stream is changed, which is an intentional side effect.

But maybe you don't mean side-effect in the computer science sense, but in some ad hoc sense.

Your second question: "For example for such statement: c += 2, c -= 1 Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?"

The answer to this is yes in the case of a statement or expression, except when the comma operator is overloaded (very unusual). However, sequences like c += 2, c -= 1 can also occur in argument lists, in which case, what you've got is not an expression, and the comma is not a sequence operator, and the order of evaluation is not defined. In foo(c += 2, c -= 1) the comma is not a comma operator, but in foo((c += 2, c -= 1)) it is, so it may pay to pay attention to the parentheses in function calls.

Koonce answered 16/10, 2011 at 14:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.