Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is one side of an assignment sequenced before the other in c++?

I understand that this is undefined behavior:

int i = 0;
int a[4];
a[i] = i++;  //<--- UB here

because the order of evaluation of i for the left hand side and the right hand side are undefined (the ; is the only sequence point).

Taking that reasoning a step further it seems to me that this would be undefined unspecified behavior:

int i = 0;

int foo(){
    return i++;
}

int main(){
    int a[4];
    a[i] = foo();
    return 0;
}

Even though there are a few sequence points on the right hand side of the = as far as I understand it is still undefined unspecified whether f() or a[i] is evaluated first.

Are my assumptions correct? Do I have to take painstaking care when I use a global or static variable on the left hand side of an assignment that the right hand does not under any circumstances modify it?

like image 308
odinthenerd Avatar asked Apr 08 '14 14:04

odinthenerd


People also ask

What is C sequence?

The C language defines the following sequence points: Left operand of the logical-AND operator (&&). The left operand of the logical-AND operator is completely evaluated and all side effects complete before continuing. If the left operand evaluates to false (0), the other operand is not evaluated.

What is the typical evaluation order for an assignment operator?

5.17 Assignment and compound assignment operators 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.

Can be used to change the order of Evaluluation expression?

The order of precedence can be altered by using parentheses around the parts of the mathematical expression that needs to be evaluated first.


1 Answers

a[i] = foo();

Here it is unspecified whether foo or a[i] is evaluted first. In the new C++11 wording, the two evaluations are unsequenced. That alone doesn't cause undefined behaviour, though. It is when there are two unsequenced accesses to the same scalar object, at least one of which is writing, where it does. That's why a[i] = i++; is UB.

The difference between these two statements is that a call to foo() does introduce a sequence point. C++11 wording is different: executions inside a called function are indeterminately sequenced with respect to other evaluations inside the calling function.

This means there's a partial ordering between a[i] and i++ inside foo. As a result, either a[0] or a[1] will get set to 0, but the program is well defined.

like image 191
jrok Avatar answered Sep 28 '22 08:09

jrok