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.
Related
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
I need some of your wisdom:
Why this cannot be done:
std::vector<int> min(INT_MIN, 3);
"C++ exception: std::length_error at memory location 0x0000009AA63CF0A0."
And this way apparently worked:
std::vector<int> min;
for (int i = 0; i < 3; ++i)
large.push_back(INT_MIN);
INT_MIN is a large negative value. It gets converted to size_t which is unsigned, and becomes a large positive value - apparently, larger than max_size().
You might have meant to create a vector with three elements, each equal to INT_MIN. In this case, you are specifying arguments the wrong way round. Make it
std::vector<int> min(3, INT_MIN);
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.
I am using fill_n() function to initialize my array values, but then I cannot change the values of the array, it is always the initial value.
Can someone explain me why is that?
#include<iostream>
#include<ctime>
int main(){
//Matrix
int m[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
int v[3] = {5,6,7};
int result[3];// = {0,0,0};
int n = 0, i, j;
std::fill_n(result,sizeof(result),0);
clock_t time = clock();
while(n<1000){
n++;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
result[j] = result[j]+(v[i]*m[j][i]); //changing the values here.
}
}
}
time = clock() - time;
for(i=0;i<3;i++){
std::cout<<result[i]<<"\n";
}
std::cout<<"Execution time: "<<((float)time)/CLOCKS_PER_SEC<<"\n";
return 0;
}
The output of the code is always 0.
By std::fill_n(result,sizeof(result),0); you are asking to fill the first sizeof(result) elements by 0.
However, only 3 elements are available in result. Thus you wrote out-of-bound and led to undefined behavior. You should write std::fill_n(result, sizeof(result) / sizeof(result[0]), 0); instead.
Note that sizeof(result) returns size of result in bytes, not in elements.
sizeof(result) returns the number of bytes held by the variable result. Since result is an array of 3 ints, its size in memory is 3 * sizeof(int), which (unless sizeof(int) is 1) much greater than 3. Thus you are writing pass array bounds and incurring undefined behavior.
The actual way to calculate the size would be to divide the entire size of result by its element type. That is, sizeof(result) / sizeof(int).
If you want to initialize each element to 0, a simpler way to do it would be to value-initialize the array:
int result[3]{}; // or = {} (pre C++11)
Number of elements (or size) of an array of type type would be sizeof(array) / sizeof(type). Second argument required for fill_n is the number of elements to fill a container (in your case, an array of type int) and not the size of an array in bytes. Naturally, sizeof(array) returns sizeof(type) times number of elements.
I have declared an array of length N (suppose). Now, I assign some values to the elements of this array using a loop (the loop variable is used as the array's index). The code's as follows:
int main()
{
int arr[4], j;
for(j=0; j<10; j++)
{
printf("%d\n", j);
arr[j] = 0;
sleep(1);
printf("%d\n\n", j);
}
return 0;
}
I expected the output to be 0 1 2 .. 9. But what actually happened was that j got reset to 0 when the assignment arr[N+2]=0 (arr[6]=0, in this case) was executed in the loop.
What's actually happening here? Am I missing something?
Your array has 4 elements and your index is out of range so you are just stomping on memory.
Given the code here, I'd expect arr[4] to reset the array, but since you mentioned that it's of length N and N+2 is what causes it, there might be some padding in your stack. In any case, when you declare the array and j, they are put on the stack. In your case, j is in a position such that when your index is out of bounds you are accessing the memory where j is.
the behaviour of the code is undefined as it has a bug. arr has a size of 4 but you are indexing past this size with j
Your array is overflowing. You defined it like this with 4 elements:
int arr[4]
But you're trying to assign 10 elements.
j is apparently located immediately after the array, so when you assign arr[6] = 0, you're clearing j.