I recently learned about the , operator and the fact that it introduces a sequence point.
I also learned that the following code led to undefined behavior:
i = ++i;
Because i was modified twice between two sequence points.
But what about the following codes ?
i = 0, ++i;
i = (0, ++i);
While I know the rules, I can't get to a conclusion. So is it defined behavior or not ?
edit: Just as #paxdiablo mentions, defined or not, this is really a bad practice which should be avoided. This question is asked solely for educational purposes and better understanding of the "rules".
Yes. = has higher precedence than ,, so this expression is equivalent to (i = 0), ++i. , is a sequence point, so it's guaranteed that the ++i occurs after the assignment.
I'm not sure whether i = (0, ++i) is defined though. My guess would be no; there's no sequence point between the increment and the assignment.
i = 0, ++i;
As the other answer pointed out it is not Undefined Behaviour.
i = (0, ++i);
The behaviour is undefined in this case because there is no sequence point between ++i and assignment to i.
i = (0, ++i, 0)
The behaviour is well defined1 in C++03, IMHO.
1 See extended discussion for a similar expression.
Related
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Undefined behavior and sequence points
(5 answers)
Closed 5 years ago.
In the legacy code base I'm working on, I discovered the line
n = ++n % size;
that is just a bad phrasing of the intended
n = (n+1) % size;
as deduced from the surrounding code and runtime-proved. (The latter now replaces the former.)
But since this code was marked as an error by Cppckeck, and caused a warning in GCC, without ever having caused any malfunction, I didn't stop thinking here. I reduced the line to
n = ++n;
still getting the original error/warning messages:
Cppcheck 1.80:
Id: unknownEvaluationOrder
Summary: Expression 'n=++n' depends on order of evaluation of side effects
Message: Expression 'n=++n' depends on order of evaluation of side effects
GCC (mingw32-g++.exe, version 4.9.2, C++98):
warning: operation on 'n' may be undefined [-Wsequence-point]|
I already learned that assignment expressions in C/C++ can be heavily affected by undefined evaluation order, but in this very case I just can't imagine how.
Can the undefined evaluation order of n = ++n; really be relevant for the resulting program, especially for intended value of n? That's what I imagine what may happen.
Scenario #1
++n;
n=n;
Scenario #2
n=n;
++n;
I know that the meaning and implications of relaying on undefined behaviour in C++, is hard to understand and hard to teach.
I know that the behaviour of n=++n; is undefined by C++ standards before C++11. But it has a defined behaviour from C++11 on, and this (now standard-defined behaviour) is exactly the same I'm observing with several compilers[1] for this small demo program
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cout << "n before: " << n << endl;
n=++n;
cout << "n after: " << n << endl;
return 0;
}
that has the output
n before: 0
n after: 1
Is it reasonable to expect that the behaviour is actually the same for all compilers regardless of being defined or not by standards? Can you (a) show one counter example or (b) give an easy to understand explanation how this code could produce wrong results?
[1] the compilers a used
Borland-C++ 5.3.0 (pre-C++98)
Borland-C++ 5.6.4 (C++98)
C++ (vc++)
C++ (gcc 6.3)
C++14 (gcc 6.3)
C++14 clang
The increment order is precisely defined. It is stated there that
i = ++i + 2; // undefined behavior until C++11
Since you use a C++11 compiler, you can leave your code as is is. Nevertheless, I think that the expressiveness of
n = (n+1) % size;
is higher. You can more easily figure out what was intended by the writer of this code.
According to cppreference:
If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined:
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
For the case n = ++n; it would be an undefined behavior but we do not care which assignment happens first, n = or ++n.
see simple example:
int a = 0;
int b = (a ++ , a + 1); // result of b is UB or well defined ? (c++03).
This was changed in c++11/c++14 ?
The result is well defined and has been since C++98. The comma operator introduces a sequence point (or a "sequenced before" relationship in later C++s) between the the write and the second read of a and I don't see any other potential reasons for undefined behavior.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
increment values in printf
I have a two double arrays x and y and integer i. My question is whether the statement:
double res = x[i] * y[i++];
is always equal to the statement:
double res = x[i] * y[i];
i++;
Is it possible that some compilers would change x[i] * y[i++] into y[i++] * x[i], which obviously produces different result?
No -- x[i] + y[i++] has undefined behavior. You're modifying the value of i and also using the value i without an intervening sequence point, which gives undefined behavior1.
In C++11 the standard has eliminated the "sequence point" terminology, but the effect remains the same -- the two are unordered with respect to each other.
No, it is undefined when the increment occurs.
The code modifies i and uses its value without an intervening sequence point, so the behavior is undefined. The language definition does not impose any requirements here.
No,
value of i++ + i++ are undefined in C and C++.
if you read a variable twice in an expression where you also write it, the result is undefined. Don't do that. Another example is:
v[i] = i++;
Undefined means its COMPILER DEPENDENT.
Some compiler could warn you also as undefined because the order of evaluation.
A very good reference for C++
1 http://www.stroustrup.com/bs_faq2.html#evaluation-order
I was just asked a question in a technical interview that I was a bit confused about.
The question was as follows:
If
int i = -1, int j = -1, and int k = -1,
and we run the following line:
++i && ++j && ++k
what would be the new values of i, j, and k? The reason I was confused is that, since we are not assigning this expression to anything, it doesn't seem like the and operators should make any difference (only the increment operators should). However, running a simple test program quickly proved that I was mistaken. Could someone explain this to me, as I have never seen this exercise before.
The key here is that && is short-circuiting.
So, ++i is evaluated first. It increments i and returns the new value, which is 0, so the rest of the expression doesn't get evaluated.
The values should be 0, -1, -1 if I'm not mistaken.
The value of the expression ++i is 0 in this case, which is to say false so the and operation shortcuts and the latter expressions are never evaluated.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
Undefined Behavior and Sequence Points
Ok we all know that i++ increments value by 1 on next line and ++i increments on same line(please correct me if i am wrong there ) so for a sample statement of c as follows:
int a=0;
printf("%d , %d",++a,a);
the expected output should be 1 , 1 but instead it gives 1 , 0
so as one might guess what i am asking here is why does the second linking of
i print 0 instead of 1 when the value is already incremented.
So if post increment didn't increment value in the same line then what is the
difference between post and pre increment? edit : changed the name of variable from i to a to avoid grammatical confusion.
You are very wrong in your understanding of the increment operators.
i++ increments i, and returns its old value; ++i increments i,
and returns the new value. When the actual incrementation takes place
is only guaranteed to be after the preceding sequence point, and before
the next; in your code, this means before the call to printf.
Beyond that (and largely because of that), if you modify the value of an
object, you're not allowed to access it anywhere else without an
intervening sequence point, except as needed to determine the new value.
You violate this rule, so your code has undefined behavior.
It's undefined behavior. the compiler is allowed to calculate the parameters in any order. your compiler just calculate it from right to left, so the rightest parameter is 0, and the 2nd is 1.
edit: as Seth said, the compiler is only free to change the order of calculating, not to do whatever it wants, so when you don't care about the order you can freely call functions, but you should never assume that one parameter is been calculated before another.
I think your question is not about how increment work. The phenomenon you have observed is about the order of passing parameter to a function. As far as I can remember, this is not defined by c++ standard, so it's a UNDEFINED BEHAVIOR. Meaning different compiler could have different implementation.
E.g.
One compiler could pass parameter from left to right, then a different could pass parameters from right to left.
You can have a better read of Sequence point here:
http://en.wikipedia.org/wiki/Sequence_point
printf("%d , %d",++i,i);
is undefined behavior.
Your are violating C sequence points rule:
(C99, 6.5p2) "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."
Once I read in some book that when a statement is like this:
printf("%d , %d",++a,a);
The execution starts from right to left but outputted as left to right. Therefore you see the out as 1 0 - 'a' is calculated first = 0 then '++a' = 1, but displayed as 1 0
This is strange but yeah that's how it works.
Hope this helps.