vector.size() - 2 leads to infinite loop - C++ [duplicate] - c++

This question already has answers here:
How do unsigned integers work
(3 answers)
Closed 2 years ago.
I am trying to run a loop on vector but not on the last two elements. So for that I used the following implementation:
vector<int> x;
for(int i=0;i<x.size()-2;i++){
cout<<"looping over element"<<endl;
}
However, running the above code with no elements inserted into x leads to an infinite loop.
Ideone link:
Why do I get this behavior? If x.size()==0 then i<-2 condition should not hold and the code should never enter the for loop

x.size() returns an unsigned value. If this is smaller than 2 then the value will underflow and the result will become very large.
On the other hand since i is a signed type hen it will sooner or later come to the max value of an int (which will still be less than the result of x.size() - 2), and then i++ will lead to arithmetic overflow which is undefined behavior.
Before you attempt this loop you must make sure that x.size() >= 2, and you need to make sure that the counter variable is an unsigned type (like size_t):
if (x.size() >= 2)
{
for (size_t i = 0; i < x.size() - 2; ++i)
{
// ...
}
}

When x.size() is smaller than 2, and you subtract two, you get some big value, as the result is unsigned, and ((someunsigned)-1) is a huge number
So the loop runs:
i=0
i=50000
i=1000000
i=4,294,967,295 //Stop
So, you have no infinite loop, only a very long running loop

Related

How to find the power of the array elements? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I need to check if A[0] ^ A[1] ^ A[2] ... ^ A[N] is even or odd.
Is this code right??
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int main(){
long long n;
cin >> n;
int a[n];
long int mp;
for(int i = 0; i < n; i++){
cin >> a[i];
mp = pow(a[i], a[i+1]);
}
if (mp % 2 == 0){
cout << "YES";
}
else cout<<"NO";
}
Do the maths first.
Consider that
odd * odd * odd * odd .... * odd == odd
You can multiply any odd factors and the result is always odd. Whether a number is odd or even is equivalent to: It has a prime factor 2. Some integer raised to some other integer cannot remove a prime factor, it can also not add a prime factor when it wasn't present before. You start with some x and then
x * x * x * x * x .... * x = y
has the same prime factors as x, just with different powers. The only exceptions is to get an odd number from an even one when you raise a number to power 0, because x^0 = 1.
Ergo, you are on the wrong track. Instead of brute force raising numbers to some power you merely need to consider ...
is A[0] odd or even
is any of the other elements 0 (remember that (a^b)^c) is just a^(b*c))
Thats it.
I will not write the code for you to not spoil the exercise. But I should tell you whats wrong with your code: pow is not made to be used with integers. There are many Q&As here about pow returning a "wrong" result, which is most often just due to wrong expectations. Here is one of them: Why does pow(n,2) return 24 when n=5, with my compiler and OS?. Moreover, you are accessing the array out of bounds in the last iteration of the loop. Hence all your code has undefined behavior. Output could be "maybe" or something else entirely. Also, your code merely calculates a[i] ^ a[i+1] and after the loop you only consider the very last result. Thats not what the task you describe asks for. Last but not least, Why aren't variable-length arrays part of the C++ standard?. Use std::vector for dynamically sized arrays.

why do for loop does not work when I use increment operations for the arrays [duplicate]

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 3 years ago.
I have two arrays in my code each one of them have 7 elements, I used a for loop:
for (int i = 0; i < 7; i++)
{
distance = x[++i] - x[i];
area = trapezoidArea(distance, y[++i],y[i]);
sum += area;
}
I wanted to calculate the area of a trapezoid. The difference of x[1]-x[0] will give me the height and y[1] is the first side, and y[0] is the second side.
This for loop doesn't work, and I want to know why.
You can't use ++ as post or pre-increment operator in this case.
This will change the value of your i variable, and therefore your for loop won't have the behaviour you want.
The proper way would be :
for (int i = 0; i < 6; i++)
{
distance = x[i+1] - x[i];
area = trapezoidArea(distance, y[i+1],y[i]);
sum += area;
}
Be careful you have to loop until i<6 because if you let 7, you'll try to access x[7+1] = x[8], and you'll have undefined behaviour or segmentation fault.
++i increases i. So you increase i thrice in one run through the loop, and on top of that, it might also be undefined behavior because of sequencing. What's the i in x[i] supposed to be? The i before the ++i in x[++i] increased it, or after it was increased?
If you want one more than i without increasing it, do i+1 instead. Replacing x[++i] with x[i+1] and likewise with y[++i] should fix this issue. But without seeing all of your code, it's impossible to say if that's the only issue.
When you do ++i in the square brackets, you actually increment the value of i by one. What you should do is i + 1 and leave ++i only in the loop declaration.

vector.size() is working unexpectedly in comparision

When I use vector.size() in comparisions it gives unexpected results
vector<int> v;
for(int i = 0; i < v.size() -1;++i){
printf("i = %d\n", i);
printf("v[i] = %d\n", v[i]);
}
since the size of vector is 0, it shoudn't print anything but, it enters for loop and prints i = 0 and give segmentation fault. But it shouldn't even enter the for loop as v.size() - 1 is -1.
Why is it happening?
The problem is your loop:
for(int i = 0; i < v.size() -1;++i)
More specifically, this part of the condition: v.size() - 1.
The size function returns a value of type size_type, which if you read e.g. this vector reference will see is an unsigned type.
That means when you subtract 1 from the value 0, you don't get -1 but instead get a very large value since unsigned underflow wraps around to its highest value.
That means your loop will indeed iterate, at least once, and lead to UB (Undefined Behavior) when you index out of bounds.
Vector size is an unsigned int, so v.size() - 1 will never be -1 but some very large integer.

subtraction from size_t results in large positive number [duplicate]

This question already has answers here:
vector size - 1 when size is 0 in C++
(5 answers)
Closed 1 year ago.
I just run into a nasty bug where I have a loop
for (auto i = 0; i < vec.size() -1; ++i) {
//
}
with vec being an emtpy std::vector, thus vec.size() -1 evaluates to 2^64 on my system.
What's the correct way of writing the above loop?
size_t is an unsigned type hence the problem, just do that this way:
for (auto i = 0U; i + 1 < vec.size(); ++i)
0U added to make i unsigned (to avoid warning), but I would better use size_t istead of auto in this case
What's the correct way of writing the above loop?
Keep the loop as it is, but add an if-condition that branches into the loop only if the vector isn't empty.

Why is my for loop crashing on a vector of doubles?

This for loop always crashes immediately:
for (auto i = v.size() - 1; i >=0; --i);
Obviously I have a whole load of code in the loop, and v is a vector of doubles. I'm trying to iterate over them in reverse order.
What is going on here?
for (auto i = v.size() - 1; i >=0; --i);
Look at vector::size() method - it returns usually unsigned int (on strange platforms it might be other unsigned type)! So your i variable will have unsigned type.
When your loop will come to step i == 0 it will decrement it and i will have value 2^32 - 1 == UNSIGNED_INT_MAX (or other positive value if you work on strange platform - see vector::size_type on your platform to see underlying type). So it will never be less then 0, it will never stop your loop. I guess when it turns so big it crashes becouse it goes out of range, but i don't see whole code to be sure.
See here - look for size_type typedef - it says its unsigned type.
You might want to use reverse iterators (see #NathanOliver's response), though i'm not very fond of them in simple loops.
Since i is unsigned it will never be less than 0. It will wrap around to the maximum value that it can hold instead.
If you want to iterate through a vector backwards then you should use a reverse_iterator
std::vector<int> foo = {1,2,3,4,5,6,7,8,9};
for (auto it = foo.rbegin(); it != foo.rend(); ++it)
std::cout << *it << " ";
This will output
9 8 7 6 5 4 3 2 1
The variable i will be an unsigned type.
That can never be less than zero.
Eventually you will access an element outside the vector as i will wrap around to the largest possible unsigned value rather than going negative
What Bathsheba said: the auto type is an unsigned. So decrementing 0 becomes some large positive number, which is >= 0 so the loop continues, but that value is outside the vector's range and causes the crash.