This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
In c++, arguments evaluation of order is not guaranteed, but is the order of left/right sub expression of assignment expression is guaranteed? For example
#include <iostream>
#include <map>
int main()
{
int i = 2;
std::map<int, int> map;
map[i++] = i--;
return 0;
}
Is left expression i++ guaranteed to be executed before right expression i--?
You asked:
Is left expression i++ guaranteed to be executed before right expression i--?
No, it is not.
The line
map[i++] = i--;
could end up being
map[2] = 3;
or
map[1] = 2;
depending on which side of the assignment operator gets evaluated first.
However, since the line invokes undefined behavior, it could also be, as pointed out in the comment by #juanchopanza, :
map[42] = -999;
Related
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 4 years ago.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{1,2,3,4,5};
int i = 0;
while (i < 5) {
cout << i+v[i++] << endl;
}
return 0;
}
Why the output of the program is "2,4,6,8,10", instead of "1,3,5,7,9"?
This is undefined behaviour because the read of the "first" i and the other i++ are unsequenced. The output is meaningless.
Further reading: Undefined behavior and sequence points,
Some compilers will warn you that you are doing something that leads to undefined behavior: Relying on the evaluation order of unsequenced expressions.
Example:
<source>:22:22: warning: unsequenced modification and access to 'i' [-Wunsequenced]
cout << i+v[i++] << endl;
The evaluation order of expressions between sequence points is not defined. The only sequence point in the expression i+v[i++] is at the end of the expression, so the compiler is free to order the addition of i and the increment of i however it wants.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
test321["abc"] = 1;
test321["abc"] = test321.count("abc") ? test321["abc"]++ : 0;
test321["abc"] = 1
test321["abc"] = 1;
test321["abc"] = test321.count("abc") ? test321["abc"]+1 : 0;
test321["abc"] = 2
Why is there a difference?
The line
test321["abc"] = test321.count("abc") ? test321["abc"]++ : 0;
has undefined behavior until C++17 since test321["abc"] is modified in two ways:
By assignment.
By the post increment operator.
It's best to avoid using such constructs. You can read more about it at Why are these constructs (using ++) undefined behavior in C?.
The second approach is well-behaved code and should be used for what you intend to do.
If you use C++17, both approaches should result in identical behavior.
The question you're posing, "Why is there a difference?", is less meaningful than you might expect, because your code invokes Undefined Behavior.
Consider the following code snippet which is, semantically, equivalent to what your code is doing:
int x = 1;
x = x++;
What is a logical result for x? Is there a logical result?
Well, if you ask the C++ standard, the answer is that there is no logical result, and it leaves the result of an operation like this to be undefined. Any given compiler is given no restrictions or limitations on what it should do with code like this, so some compilers will work out that a logical result is for x to equal 2, and some compilers will work out 1 instead. Some compilers might (rarely) do something else entirely.
For more on this particular phenomenon, see this related Question.
To avoid undefined behavior, you should prefer constructs like this:
auto & ref = test321["abc"];//We save the reference to avoid performance issues
//Note that the brackets operator will create an entry if it doesn't already exist, negating
//the need for a check to count(); count() will always return at least 1.
ref = 1;
ref = ref + 1;
Or
if(auto & ref = test321["abc"])
ref++;//Will only increment if value was not 0.
This question already has answers here:
Semicolon at the ends of if-statements and functions in C
(7 answers)
Closed 5 years ago.
#include <iostream>
int main() {
for( int i = 0; i < 5; ++i) {
std::cout << "Hello" << std::endl;
};
}
Is there any case that the semicolon after the for loop would affect the program ?
The semicolon is an empty expression statement.
From section 6.2 of the C++ standard
The expression is a discarded-value expression (Clause 5). All side
effects from an expression statement are completed before the next
statement is executed. An expression statement with the expression
missing is called a null statement. [ Note: Most statements are
expression statements — usually assignments or function calls. A null
statement is useful to carry a label just before the } of a compound
statement and to supply a null body to an iteration statement such as
a while statement (6.5.1). —end note ]
This will be more clear with some reformatting:
#include <iostream>
int main(){
for(int i=0; i<5; ++i){
std::cout <<"Hello"<<std::endl;
}
;
}
The presence of this null statement has no effect on the program.
No.
The semicolon is not even "attached" to the loop; it's just an empty statement sitting there, effectively on its own.
It doesn't change anything. It just evaluates to an empty statement.
It's completely harmless. Just a bit of pointless clutter.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 7 years ago.
I have here an equation i can't understand how c++ process this. Can someone explain this operation?
code:
#include <stdio.h>
main(){
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int i = 0;
int num = a[i+++a[++i]]+a[++i+i++];
printf("\nnum1: %d i: %d,num,i);
}
why is the answer num = 9 while index i is just equal to 4;
Using ++ twice in the same expression on the same variable is explicitly undefined by all versions of both the C and C++ standards, and so i does not necessarily equal 4. It could be anything at the whim of the compiler writer.
Never do this. Never use ++ and -- twice in the same expression. There is no way to make any statement about what the resultant value will be, and no experience with what it does with one compiler will mean anything with respect to what another compiler does.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
Example code
int arr[3] = { 0, 1 };
int* buf = arr;
*buf++ = *buf + 10;
Result of last expression is that buf[0] == 10. I taught it would be buf[0] == 11.
A college of mine wrote something similar to the example code and I taught it works differently than it does. And I would like to know why it works the way it does.
The way I went about figuring it out was to look at the operator precedence table. There it states that suffix ++ has precedence over dereference. Hence I taught that on the left of operator= buf would point to the first element, but on the right of the operator= it would have already been incremented and would point to the second element. However that is not the case.
My question is, why is that so? Preferably a standard quote :) However any explanation is welcome!
You are accessing and modifying the pointer multiple times in a single sequence point. This is undefined behavior.
More generally, reading from and writing to any variable between sequence points is undefined. The fact that you have a pointer in this specific example is by-the-by.
To avoid confusion with the pointer:
int i = 0;
i++ = i + 1; // UB
Logically, should the i on the right hand side be the "current" value of i, or the modified value? This is why it is undefined. Instead, separate the code:
int i = 0;
++i;
i = i + 1;
Which is clear, and well defined.