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.
Related
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.
I read this answer about undefined behaviour, where I saw following statement:
++++++i; // UB, parsed as (++(++(++i)))
I don't think it is undefined behaviour. I have a doubt, Is it really UB in C++? If yes, then How?
Also, I made program and compiled using g++ prog.cpp -Wall -Wextra -std=gnu++1z -pedantic command, it's working fine without any warning. It's give an expected output.
#include <iostream>
using namespace std;
int main()
{
int i = 0;
cout<<++++++i<<endl;
}
In C++03 it is undefined behavior. In C++11 it is not. There is no sequence point between the various pre-increments. If i was a user-defined type, it would be well-defined behavior because then there would be a function call (a sequence point).
In C++11, the idea of sequence points was replaced with sequenced before/sequenced after. Defect 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637) provides an example of a previously undefined construct becoming well-defined (i = ++i + 1).
To understand why it's not undefined behavior, let's look at the pieces we need. ++i is equivalent to i = i + 1 (except i is evaluated only once). Further if we substitute i = i + 1 with inc, ++(i = i + 1) becomes inc = inc + 1.
[expr.ass] states:
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.
Thus the assignment in i = i + 1 is sequenced before value computation of inc; however, the assignment in inc = inc + 1 is sequenced after value computation of inc. There is no undefined behavior because the assignments are sequenced.
Sometimes behavior is undefined even though it's hard to imagine how it could be mishandled. But pre-C++11, this was undefined because the same object is modified multiple times without an intervening sequence pointed.
One could imagine a compiler that "optimized" the code by consolidating all the modifications to i. Thus each increment winds up incrementing the original value. But that's not the point. UB is UB if the standard says so. It doesn't matter whether or not we can imagine ways it can fail.
This question already has an answer here:
Difference between a+++++b and a++ + ++b [duplicate]
(1 answer)
Closed 7 years ago.
#include <stdio.h>
int main()
{
int c=10,b;
b=++c+++c;
printf("%d",b);
return 0;
}
Could someone please let me know,why it is throwing compilation error?
The gibberish is tokenised as
++ c ++ + c
and parsed as
((++c)++) + c
This tries to increment the rvalue yielded by ++c, which isn't allowed. You can only increment an lvalue (or a class type, in C++).
Even if it were allowed, this would give undefined behaviour: you'd have an unsequenced modification and use of the value of c.
The compilation error would be solved if you put a space in ++c + ++c
b = ++c + ++c;
But that just fixes the compilation error. What you are doing is Undefined Behavior. Trying to change the value of c more than once in the same expression using ++ will lead to undefined Behavior.
Read Why are these constructs (using ++) undefined behavior?
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:
Undefined behavior and sequence points
(5 answers)
So why is i = ++i + 1 well-defined in C++11?
(3 answers)
Closed 9 years ago.
I know this looks familiar but it is brought to me as a problem in a test by Microsoft to recruit interns. It seems to me that y=++y is not standard compliant, but I think maybe it would be better to be sure (not sure that I'm better than those who write up these tests at MS). So I'm asking your advice. Do you think expressions like this is standard-compliant and does not result in undefined behaviour?
#include <stdio.h>
int main(){
int a = 10;
int b = 10;
a = ++a; //What ???
b = b++; //What ???
printf("%d %d\n",a,b);
return 0;
}
gcc complains about it when used to compile with -Wsequence-point. (It is not explicitly stated whether it is a C or C++ specific problem.)
But only four answers provided:
a) 10 10
b) 11 10
c) 10 11
d) 11 11
Although one is not restricted to select only one answer ( so maybe I should choose all four? )
Well, in my opinion, between self-incrementing and assignment there is no sequence point. So this violates the specification. Doesn't it?
They're both well-defined behaviour as per C++11. C++11 doesn't even have sequence points, so a sequence-point related warning is obviously outdated. The assignment operator imposes sequencing on its arguments.
Edit:
Whilst everyone can agree that i = ++i is now well-defined behaviour, it is rather non-trivial to decide the definedness of i = i++. Intuitively, I should describe it as well-defined, but the Standard clearly states that
i = i++ + 1;
is UB, and I'm not seeing the + 1 making any difference here.
The short is, if you wanted to answer this question, you would need to be an expert on the decidedly non-trivial C++11 sequencing rules, which it appears that I am not, but it appears that the answer is "None of the above because UB".
As per C++03 standard,
Both of the below statements result in undefined behavior:
a = ++a;
b = b++;
As you correctly stated, g++ points out below warning:
warning: operation on ‘a’ may be undefined [-Wsequence-point]
Note that in case of UB, the answer can be anything apart from (a), (b), (c), (d).
Ideally there should be an option for "undefined behavior" in the test question. But often, the person who prepares the question would simply compile in XYZ compiler and submit it.
Here is a related SO post explaining Undefined Behavior and Sequence Points.
a = ++a;
b= b++;
These operations are considered as undefined.
Each compiler can do as its wish. output varies on compiler the examiner framed the question.
I think it's D) since ++a means increment a and then execute the operation, so it will be like doing a=11. b++ means do the operation and then increment, so you'll be assigning b=10 but then b is incremented giving it the value b=11.
Well for the purists: It doesn't "mean anything and then anything", but that's it's behavior. I tested it (using visual c++ and g++) and my answer is correct a=11 and b=11.