This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
Why does not C/C++ evaluates expression in order of left to right in these cases:
Initially x=1
Evaluating x + ++x gives 4.
If normal evaluation is carried out (precedence of ++ is higher than +) then the result should be 1 + 2 = 3
Similarly:
x + ++x + x gives 6
x + x + ++x gives 4
Why are results different?
More Cases:
x + x++ +x gives 5
What rule is followed by C/C++ instead?
Specifically the results of these expressions are not defined, this is because of Cs requirement for multiple accesses (excluding cases where all accesses are reads) to always have a sequence point between them (such as a ; or ,). The results you are getting there are effectively random and would depend on your compiler or theoretically could even change between runs of your program, please see here for information on sequence points:
http://en.wikipedia.org/wiki/Sequence_point
And here if you want to learn about undefined behavior (what your misuse of the variable causes):
http://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C_and_C.2B.2B
Related
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 3 years ago.
The code:
int a = 0;
a = ++a % 5;
causes the warning:
warning: operation on 'a' may be undefined [-Wsequence-point]
a = ++a % 5;
~~^~~~~~~~~
with various compilers such as gcc when compiling with -Wall
Yet this code, works fine?
int a = 0;
a = (a + 1) % 5;
Why is this a warning, and can it safely be ignored?
Wrapping it in brackets etc. doesn't seem to make the warning go away.
Edit: For clarification, I was using C++17 compiler when seeing these warning messages.
a = ++a % 5;
a is modified two times. Before C++11, this is undefined behavior — it is not specified that the increment is committed before the assignment. Since C++11, the side effect of the pre-increment on the RHS is guaranteed to be evaluated first, and a is guaranteed to be 1.
a = (a + 1) % 5;
Here, a is only modified one time. The resulted a is guaranteed to be 1.
Per comment: operator precedence does not determine the order of evaluation. Although assignment has higher precedence, the order of evaluation is still unspecified (prior to C++11).
EDIT:
Before C++11: Because with ++a you're modifying a while you're modifying a through assignment, therefore undefined behavior.
After C++11: See #L.F.'s answer.
This question already has answers here:
New Sequence Points in C++11
(2 answers)
So why is i = ++i + 1 well-defined in C++11?
(3 answers)
Closed 4 years ago.
I've read something about order of evaluation and I understand some mistakes caused by order of evaluation.
My basic rule comes from a text and example:
Order of operand evaluation is independent of precedence and associativity.
In most cases, the order is largely unspecified.
So for expression like this: int i = f1() * f2();
f1 and f2 must be called before the multiplication can be done. After all, it is their results that are multiplied. However, we have no way of knowing whether f1 will be called before f2 or vice versa.
Undefined behavior examples:
int i = 0;
cout << i << " " << ++i << endl;
How I understand: I treat i and ++i as a function. I don't know which evaluates first, so the first i could be 0 or 1 and (the rule) makes sense.
while(beg != s.end())
*beg = toupper(*beg++); //Just another example.
I think the key to understand this is to treat each operand as a "evaluation unit", and one don't know order of evaluation within these units but can know order in every single unit.
But for i = ++i + 2 reference here, Why is it wrong? I can't explain with my own conclusion.
The left i is used as a lvalue and not a pointer. ++i simply rewrite the original value and doesn't change the storage address. What could be wrong if it evaluates first or latter? My rule fails here.
Quite long but try to provide enough background info, thank for your patience.
I don't know sequence point which is mentioned frequently in answers.. So I think I need to read something about it first. Btw, the debate is not very helpful, for a newbie simply want to know why is it considered wrong, like before C++11?
I find this answer Undefined behavior and sequence points explain well why i = ++i + 2 is undefined behaviour before C++11
C++11 has new sequencing rules. In particular, for a pre-increment (++i) the side effect (writing the new value) is sequenced-before the further use of the new, incremented value. Since the assignment i= is sequenced-after the evaluation of its right-hand side, this means the write ++i is transitively sequenced-before the write i=(++i + 2)
It would be another matter for i=(i++ + 2). For post-increment, the side effect is sequenced-after, which means the two assignments are no longer sequenced relatively to each other. That IS undefined behavior.
Your two "subfunctions" in i = ++i + 2 are an explicit assignment made by the = operator and an implicit assignment done by the ++ operator.
The preincrement operator is defined to return an incremented value of the variable, and this definitely shall be used for addition (performed by the + operator). However, it was not defined, when the incremented value should be stored back into i.
As a result, it was undefined whether the final value of i is old_i incremented plus 2 or just old_i incremented.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
Why do we get different results for the two follow statements:
int x = 5;
x = x * x++;
the output is 26; whereas the next example returns 30, though they are same?!
int x = 5;
x *= x++;
Thank you
These both exhibit undefined behaviour in both C++03 and C++11. In C++11 terminology, you can't have two unsequenced modifications of the same scalar or a modification and a value computation using the same scalar, otherwise you have undefined behaviour.
x = x * x++;
In this case, incrementing x (a modification) is unsequenced with the other two value computation of x.
x *= x++;
In this case, incrementing x is unsequenced with the value computation of x on the left.
For the meaning of undefined behaviour, see C++11 §1.3.24:
undefined behavior
behavior for which this International Standard imposes no requirements
Assigning a ++'d value to the original value is undefined behavior. So it makes sense that assigning a ++'d then multiplied value is also undefined.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
I do not understand why the output of following program is 63:
#include <iostream>
int main() {
int a = 20;
a += a + ++a;
std::cout << a;
}
I was expecting it to be 61. What exactly a += a + ++a; does?
Standard says: "Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression" (5 Expressions, §4), i.e. the following:
a += a + ++a
yields undefined behavior just like:
a = ++a;
does already. It also says: "the prior value shall be accessed only to determine the value to be stored", i.e. if you want to change a, you can use a in the same expression just to retrieve the previous value:
a = a + 1; // OK
... "otherwise the behavior is undefined."
You're triggering undefined behavior and there is no 'correct' answer. Your compiler can chose what order to evaluate the arguments of the plus operator.
it looks like ++a is evaluating before the rest of the expression, so it's as though a is 21` in a statement like
a += a + a;
at any rate, don't use ++a inside of an arithmetic expression like that anyway. It's confusing for people, and is probably undefined behavior
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
I'm having my lecturer class right now and my lecturer mention an expression as follows:
int a , b;
a = 4;
b = a++ + a--;
The Question
My lecturer says this expression value can be defined: that it is 8. Which means both a value 4 is summed and assign to b before it's incremented and decremented.
But to me, I think this expression answer is kinda vague and the result will be based on the compiler implementation. That's because to me, the compiler might do the a++ part first—that is, use the value 4 and incremented the a to 5, after that the expression is 4 + 5 = 9 and is assigned to b then only the a is decremented.
It might also do the a-- part first by using the value 4 and decremented it by 1 to 3, and later on sum the value 4 with 3 and assign the value to b then only incremented the a back to 4.
My question is who's correct, my lecturer or me? Because I don't wanna get confused with it and later on will be a problem for me.
Your lecturer is wrong. Writing to the same variable twice without an intervening sequence point is undefined behaviour. From the spec, J.2 Undefined behaviour:
Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored (6.5).
The reference is to 6.5 Expressions, paragraph 5:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
Annex C of the C spec has a handy list of all of the sequence points:
The following are the sequence points described in 5.1.2.3:
The call to a function, after the arguments have been evaluated (6.5.2.2).
The end of the first operand of the following operators: logical AND && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma , (6.5.17).
The end of a full declarator: declarators (6.7.5);
The end of a full expression: an initializer (6.7.8); the expression in an expression statement (6.8.3); the controlling expression of a selection statement (if or switch) (6.8.4); the controlling expression of a while or do statement (6.8.5); each of the expressions of a for statement (6.8.5.3); the expression in a return statement (6.8.6.4).
Immediately before a library function returns (7.1.4).
After the actions associated with each formatted input/output function conversion specifier (7.19.6, 7.24.2).
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call (7.20.5).