#include <iostream>
#include <cmath>
#define max(x,y) (x)>(y)? (x): (y)
int main() {
int i = 10;
int j = 5;
int k = 0;
k = max(i++,++j);
std::cout << i << "\t" << j << "\t" << k << std::endl;
}
No, it doesn't.
In this case the situation is saved by the fact the ?: operator has a sequence point immediately after evaluating the first operand (the condition) and after that only one of the two expressions (second or third operand) is evaluated. Your code is equivalent to
...
bool c = i++ > ++j;
k = c ? i++ : ++j;
...
No undefined behavior here.
Well, there certainly are a lot of problems with it.
max is actually computing min
increment operators are doubled on whatever choice is selected since you are using a macro
using postfix/prefix increments is just thrown in to confuse, but doesn't have a lot of bearing on the problem.
This code will produce the same results each time run, so no, it's not undefined. At the cout:
i = 11
k = 7
j = 7
This sounds like a bad homework problem. :)
Related
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 2 years ago.
I was trying to make a 'smart' optimization when I stumbled upon some weird behavior, so I created a minimal example to replicate it.
In the code below, I create an array and shift elements to the left, then print the array.
The code works exactly like one would expect.
#include <iostream>
int main()
{
int array[5]{0,1,2,3,4};
for (int i = 0; i < 4; ++i)
{
array[i] = array[i + 1]; // Array becomes {1,2,3,4,4}
}
std::cout << "Printing array: ";
for (int i = 0; i < 5; ++i)
{
std::cout << array[i]; // Prints {1,2,3,4, 4}
}
std::cout << "\n";
}
Now, looking at the first for block, I thought I could spare one i increment.
So I tried to rewrite that block as follows:
for (int i = 0; i < 4;)
{
array[i] = array[++i]; // Expected: array becomes {1,2,3,4,4}
}
This does not work, however.
i is in fact updated, because the program does not loop, but the assignment does not go as expected and the terminal outputs Printing array: 01234.
Now, it might have been that the expression on the right is evaluated before the expression on the left, in which case this behavior would be explained.
However, I also tried the following reverse iteration:
for (int i = 4; i > 0;)
{
array[--i] = array[i]; // Expected: array becomes {1,2,3,4,4}
}
And it also outputs Printing array: 01234.
In both cases, I tried compiling in debug mode, in case it was some weird compiler optimization responsible for it, but the result was still the same.
Prior to C++17, it is undefined behavior,
Since C++17, we have
Order of evaluation
20) In every simple assignment expression E1=E2 and every compound assignment expression E1#=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1.
So
array[i] = array[++i];
array[++i] is evaluated first, (incrementing so i)
array[i] is evaluated after, with i incremented.
So it is mostly equivalent to
++i;
array[i] = array[i]; // Noop
And for
array[--i] = array[i];
it is mostly equivalent to
array[i - 1] = array[i];
--i
You are invoking undefined behavior because the order of evaluation in an expression is unspecified. Don't read and write from/to an object in the same expression. The offending lines are:
array[i] = array[++i];
and:
array[--i] = array[i];
This was changed in the C++17 standard and if you compiled with C++17 support, you would not invoke undefined behavior.
Is this code undefined behavior due to accessing out of bound element in the first for loop?
int main() {
std::size_t length = 4;
int* a = new int[length];
for (std::size_t i = 0; i < length; )
a[i] = ++i;
for (std::size_t i = length - 1; i >= 0; i--)
std::cout << a[length - 1] << " ";
}
If shrotly, yes, it is. In this situation C++ doesn't define in which order expression must be calculated, because both sides have side effects. So one compiler can firstly calculate left side, second can calculate at first right side. But if you look at this, you can find that
a[i] = i++; // undefined behavior until C++17
So, you can use this line, only if you use C++ 17.
Hello all I'm having difficulty running some code under various circumstances. I have code that finds how many prime numbers there are, of all the numbers in an array, times how long it takes, and prints how many prime numbers there are. This all works fine, but then I need to run the same code, but with a char array. That is where the problems come in. Here is the code, with an array of ints:
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <stdio.h>
using namespace std;
static const int N = 1000;
int main()
{
int i, a[N];
clock_t start = clock();
for (i = 2; i < N; i++) a[i] = i;
for (i = 2; i < N; i++)
if (a[i])
for (int j = i; j*i < N; j++) a[i*j] = 0;
start = clock() - start;
int primes = 0;
for (i = 2; i < N; i++) {
if (a[i]) {
primes++;
cout << " " << i;
if (primes % 10 == 0)
cout << "\n";
}
}
printf("\nIt took %d clicks (%f seconds) to find all prime numbers.\n", start, ((float)start) / CLOCKS_PER_SEC);
cout << "The number of primes out of " << N << " integers is " << primes << endl;
return 0;
}
When I simply replace 'int' with "char" for the array, and set 'N' to something like 10, or 100 it works just fine, save for how the prime numbers look. Anything higher and nothing prints off. I know its not as simple as just changing where it says 'int' to 'char' but I am hopelessly lost on the subject. Doesnt help that I need to do this again, but changing the array to type bool (which doesnt make much sense to me either.)
Any kind of insight or simple solution would be wonderful. I will keep searching for something in the meantime. Thanks!
The problem is that you're storing i into a[i]. When a is a char array, the maximum value of an element is 127 (if char defaults to signed) or 255 (if it's unsigned), assuming a typical system with 8-bit bytes. If it's signed, overflow results in implementation-defined behavior; if it's unsigned, overflow wraps around modulo 256.
The only thing you care about is whether the value of the element is zero or non-zero, so there's no need to put different values in them. Just initialize them all to 1.
for (i = 2; i < N; i++) a[i] = 1;
This will also work when you change it to boolean.
I have a for loop where I'm using the slide operator as I'm working with unsigned types. Essentially it boils down to
for (std::size_t i = 6; i --> 0;){
cout << i;
}
But it outputs the numbers from 5 to 0 inclusive and omits 6. Why?
Thank you very much for looking at this. I'm quite stuck.
This is a touchstone for
The fact that this so-called "operator" should be used with caution, if at all.
Changing the state of variables within the conditional check of a for loop ought to be done with extreme caution, if at all.
The largest output is 5 simply because i is decremented as a result of the conditional test which also decrements i. The conditional check is ran before program control enters the for loop body.
You really ought to rewrite the loop. Don't set the initial value of i to 7 as that's a dirty hack. Although --> is often used with while (and to emphasise, it's unlikely to win you many friends in your programming review), I've never seen it used with a for loop before.
--> is not a slide operator.
It is understood by the compiler as two different operators -- and >.
So your code look like this to the compiler:
for (std::size_t i = 6; (i--) > 0;){
cout << i;
}
Since the loop condition is checked before entering the loop's body i is decreased before the first execution of the loop's body, hence the produced sequence of numbers is 5 4 3 2 1 0.
For more details see this Stack Overflow question: What is the "-->" operator in C++?
After evaluating this condition in the for statement
i --> 0
i will be equal to 5. So the first iteration of the loop outputs
5
To achieve the effect you want rewrite the loop the following way
#include <iostream>
int main()
{
size_t i = 6;
do
{
std::cout << i;
} while ( i-- > 0 );
return 0;
}
The program output is
6543210
Another way is the following
#include <iostream>
int main()
{
for ( size_t i = 6; std::cout << i && i != 0; i-- )
{
//
}
return 0;
}
Of course you could write the loop like this
const size_t N = 6;
for ( size_t i = N + 1; i-- > 0; )
// ^^^^^^^
{
std::cout << i;
}
However in general this approach does not work when the initial value of i is equal to std::numeric_limits<size_t>::max() Because if to add 1 to this value you will get 0.
A general approach using a for loop can look the following way
#include <iostream>
int main()
{
const size_t N = 6;
for ( size_t i = N, j = N; j != 0; j = i-- )
{
std::cout << i;
}
return 0;
}
Its output is
6543210
I am beginner in C++. What I understand is that:-
i++ is executing first, then increment, ++i is increment first, then execute,i+=1 is increment by 1,then execute. But in the FOR loop:
for (i=0;i<10;i++)
for (i=0;i<10;++i)
There is really no difference in these two loops above.
Here is another one to calculate the sum of all integers from 1 to 100:
int i=1, sum=0;
while (i<=100)
{
sum+=i;
i++; //i+=1; ++i;
}
cout<<sum<<" "<<i<<endl;
return 0;
But if I replace i++ with i+=1 or ++i, they all return a sum of 5050 and i of 101. So I really don't see any difference in them.
So could anyone explain this to me? Which one of those is used most in programming? Thank you!!
You are correct. In your examples there is no difference.
But here there is:
int i = 0;
cout << i++ << endl; //prints 0
cout << i << endl; //prints 1
vs
int i = 0;
cout << ++i << endl; //prints 1
cout << i << endl; //prints 1
Which one of those is used most in programming?
Most of the time, ++ is the only operation in the statement (FYI, a for loop has three statements).
If it isn't, then it might matter, and you'll use whichever one gives you the correct behavior.
FYI
Some developers have the opinion that if pre and postfix operators should always be used alone (not part of a large statement). They can lead to confusing code, or even undefined behavior.
For example,
int i = 0;
cout << i++ + i++ << endl;
has undefined behavior.
So could anyone explain this to me?
What i++ does is return the current value of i and then increment it by one, and ++i first increment i by 1 and then returns the value of i.
Take a look at this, for example:
i = 5;
j = 5;
res = i++; //res = 5, but i=6
res = ++j; //res = 6 and j=6
Which one of those is used most in programming?
Both are used depending on what you want or may be how you want.
One more thing to note:
++i is an l-value, but i++ is not. For details see here
Your analysis is correct. i++ will return the value of i, then increment, whereas ++i will increment the value of i, then return the new value. i += 1 will do the same as ++i. The difference in where they will be used in actual code is primarily situational; there's no specific answer as to where each of them are most often used or helpful. It all depends on what you want to do.
Here's a contrived example of one time it might be useful to use post-increment (i++ form):
// Return the length of a string, including the null byte
int stringLength(char str[])
{
int length = 0;
while (str[length++] != 0);
return length;
}
If you wanted to return the length without the null byte, you could modify the above example slightly, using the ++i form:
// Return the length of a string, without the null byte
int stringLength(char str[])
{
int length = -1;
while (str[++length] != 0);
return length;
}
As for i += 1, I don't think I've ever done quite that, since you can use pre- or post-increment instead. I've generally only used the compound assignment operators for values other than 1.
I think if you imagine how the for loop works you can understand the problem at hand.
for loop
initialization --> i = 0
<check condition> --> i<10? ------->--------------------
| | |
^ |yes(i.e condition not met) |no(i.e condition met)
| V V
| --------------
| |body of loop|
| --------------
| |
| V
-------<------------increment i (**) exit for loop
** increment i means i++ or ++i
i++ can be replaced by this :
int temp = i;
i = i + 1;
temp will be useless here so the compiler will optimize it to just inc i instruction. even if it doesn't do that temp is just a waste of space that's all.
++i can be replaced by
i = i + 1;
int temp = i;
again temp is not required so the compiler will just replace it with inc i instruction.
if you see both the instruction are the same because they are not being assigned to anything. only i is being affected by the increment. so both are essentially the same. this is true if i is a built-in type .
you see that the increment instruction is placed after the body of the loop? can you now see that this is almost similar to the while loop that you showed?
it is always nice to think of loops in this way.