I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];
Related
#include<iostream>
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
int main() {
int n;
std::cout << "Enter a Number";
std::cin >> n;
int result = fastFibonacci(n);
std::cout << result << "\n";
return 0;
}
in this code when i enter input 0 or 1 get correct answer. But the problem is that when i replace int numbers[n+2]; with the commented part it start giving me wrong answer when input is 0 or 1. why? anyone please explain me.
In this function
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
there is used a variable length array with n + 2 elements declared in this line
int numbers[n+2]; // int numbers[n].
Variable length arrays is not a standard C++ feature. It can be implemented as own language extension of a C++ compiler.
Using the variable length array makes the function very unsafe because there can occur a stack overflow.
As within the function there is explicitly used two elements of the array
numbers[0] = 0;
numbers[1] = 1;
then the array shall have at least two elements even when the parameter has a value less than 2.
To calculate the n-th Fibonacci number there is no need to declare an array of such a size.
Apart from this the function argument shall have an unsigned integer type. Otherwise the function can invoke undefined behavior if the user passes a negative number.
Also for big values of n there can be an integer overflow for the type int.
The function can be implemented in various ways.
Here is one of possible its implementations.
#include <iostream>
#include <functional>
unsigned long long fibonacci( unsigned int n )
{
unsigned long long a[] = { 0, 1 };
while ( n-- )
{
a[1] += std::exchange( a[0], a[1] );
}
return a[0];
}
int main()
{
const unsigned int N = 10;
for ( unsigned int i = 0; i < N; i++ )
{
std::cout << i << ": " << fibonacci( i ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
int numbers[n+2]; is the declaration of an array of ints with space for n + 2 ints, this is a variable lenght array and is not part of C++ standard, though some compilers allow it it's not somenthing you should use.
If you need a variable lenght array use std::vector.
With int numbers[n+2]; if n is equal to 0 you still have space for 2 ints, if you have int numbers[n]; the array will have space for 0 ints, so the code will fail because you are trying to access memory that does not exist with numbers[0] and numbers[1].
There are several good ways to implement the Fibonacci sequence, in the site you can find many questions regarding this matter in several programming languages, here is one of them Fibonacci series in C++
Edit
So I've seen your comments about using a vector, for making the sequence you wouldn't need the vector just two variables to store the two numbers to add, to store the sequence in a vactor, you can do somenthing like:
#include <iostream>
#include <vector>
#include <iomanip>
//passing the vector by reference
void fastFibonacci(unsigned long long n, std::vector<unsigned long long>& sequence) {
unsigned long long first = 0;
unsigned long long second = 1;
sequence.push_back(first); //add first values to the vector
sequence.push_back(second); //add first values to the vector
for (unsigned long long i = 0, value = 0; i < n && value <= LLONG_MAX ; ++i) {
value = first + second;
first = second;
second = value;
sequence.push_back(value); //adding values to the vector
}
}
int main() {
unsigned long long limit; //number of values in the sequence
int num = 1;
std::vector<unsigned long long> sequence; //container for the sequence
std::cout << "Enter upper limit: ";
std::cin >> limit;
fastFibonacci(limit, sequence);
//print the sequence in a range based loop formatted with <iomanip> library
for(auto& i : sequence){
std::cout << std::setw(4) << std::left << num++ << " " << i << std::endl;
}
return 0;
}
If you want to print just one of the numbers in the sequence, just use, for instance:
std::cout << sequence[10];
Instead of the whole vector.
The code you post in the comment to the other answer won't work because the access to the vector is out of bounds in numbers[i] = numbers[i - 1] + numbers[i - 2];, if for instance i = 5, your vector only has 2 nodes but you are accessing the 6th node numbers[5].
I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];
I expect "match!" when the n2 tail is the same that the n1 tail, otherwise, "do not match!".
Example of "match!": n1 = 123456 and n2 = 3456.
The problem is when I enter, for example, n1 = "45" and n2 = "645". It should not match, but the output is "match!".
bool different_tail = false;
char n1[11], n2[11];
cin >> n1 >> n2;
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
if(i < 0 || n1[i] != n2[i-(strlen(n1)-strlen(n2))]){
different_tail = true;
break;
}
}
if(different_tail)
cout << "does not match!" << endl;
else
cout << "match!" << endl;
I don't want to use other ways to solve the problem (like, strcmp, etc...), I want to understand what's happening.
What happens is that with n1 being 45 and n2 being 645, the loop variable i will start at -1, i.e. it is negative.
However, strlen yields an unsigned value (a value of type size_t). When comparing a signed with an unsigned value (as you do in the expression i < strlen(n1)), the signed value is converted to an unsigned value. Since it's negative, this causes an underflow, so i is a very large value -- larger than strlen(n1).
You can observe the same effect with e.g.
int i = -1;
size_t x = 5;
if (i < x) {
cout << "yes\n";
} else {
cout << "no\n";
}
This program prints no.
You can avoid your issue by casting the return value of strlen, i.e. change your loop condition to
i < static_cast<int>(strlen(n1))
This question (and the accompanying answers) provide a more in-depth discussion of this topic.
Look at this line:
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
here i is an int whereas strlen(n1) is an size_t(an unsigned integer type). Performing "less than" operator between signed and unsigned type will convert all operands to unsigned types, in this case unsigned(i) becomes a very large integer, so the for loop is never executed.
BTW, it's not a good practice to use strlen in for loop, since strlen is an expensive function and will be called at every iteration. You can store strlen result in an variable and use the variable instead.
Working through a simple problem, but getting a segmentation fault because the program is writing past the end of the array.
#include <iostream>
#include <stdio.h>
static const int N = 46350;
int main()
{
int* intarray = new int[N];
for (int i = 2; i < N; ++i)
{
intarray[i] = 1;
}
for (int i = 2; i < N; ++i)
{
if (intarray[i])
{
for (int j = i; j*i < N; ++j)
{
printf("before i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
intarray[i*j] = 0;
printf("after i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
}
}
}
delete [] intarray;
return 0;
}
Console output:
before i: 211 j: 219 array: 0x21dd24c
after i: 211 j: 219 array: 0x21dd24c
before i: 46349 j: 46349 array: 0x2488aec
This doesn't happen for N = 46349. Not sure what's going on.
Integer overflow is causing this. The product of i and j overflows the range of type int and produces a negative value, which obviously compares as "less than N". Later you attempt to modify memory at that negative index i * j, which leads to unpredictable results. In fact, the overflow itself is already producing undefined behavior.
For this value of N you can get away with using unsigned int type instead of int type. The former has two times larger positive range. But in general case you have to remember that a product of two int value does not necessarily fit into the range of int type.
In your case i can become as large as 46349 and 46349 * 46349 = 2148322500, which is greater than the typical upper limit of signed 2's-complement 32-bit integer 2147483647.
The version with N=463549 is formally also broken in the very same way, except that you got lucky with that version. The if (intarray[i]) check prevents the inner cycle from running in situations where it would lead to overflow.
The maximum integer (int) in your case is 2^31-1, which is 2147483647. The square root of that number is 46340.95... So when you multiply i * j you are getting an integer overflow, the result looks negative, and it appears to be < N and is allowed through in the loop. So you get a fault. So really, anything above 46340 and you could have some problems.
There are two loops below. The first one works well while the second one is an infinite loop. Why?
for (unsigned int i=0; i<3; ++i)
{
std::cout << "i= " << i << std::endl; // this gives proper result
}
for (unsigned int i=3; i>=0; --i)
{
std::cout << "i= " << i << std::endl; // infinite loop
}
An unsigned int can never be less than 0. That's what makes it unsigned. If you turn on some warning flags, your compiler should tell you about your problem: i >= 0 is always true for an unsigned value.
Clang, for example, required no special flags at all to warn:
example.cpp:5:29: warning: comparison of unsigned expression >= 0 is always true
[-Wtautological-compare]
for (unsigned int i=3; i>=0; --i)
~^ ~
1 warning generated.
GCC required -Wextra:
example.cpp: In function ‘int main()’:
example.cpp:5: warning: comparison of unsigned expression >= 0 is always true
unsigned int cannot be less than zero (which is what loop's condition is checking). When i in your second loop is decremented from 0, it wraps around to UINT_MAX and the loop goes on.
The other answers (so far) are all correct; since i is unsigned, i >= 0 is always true, and so you have an infinite loop.
But that doesn't tell you how to fix it. If you want to iterate over an unsigned range from, say, 3 down to 0, there doesn't seem to be a straightforward way to do it. Other than changing the type of i or the direction of the range (and there may be reasons you can't do that), you could do this:
for (unsigned int i=3; ; --i)
{
std::cout << "i= " << i << std::endl;
if (i == 0) break;
}
It's not as clean as a simple for loop with no break but it does the job.
In addition to Keith Thompson's answer, there is another way to write it that doesn't require a break inside the loop:
for (unsigned int i = 3; i--; ) {
std::cout << "i= " << i << std::endl;
}
Notice how i-- acts both as the termination condition and as the afterthough, all in one. The use of the postfix decrement operator is important because it guarantees you're actually executing the loop 3 times, starting at 2 on the first iteration and ending at 0, included.
The minimum value for unsigned int i is 0; anything else would be negative and require a sign bit which is specifically what an unsigned int won't have.
So i >= 0 will always evaluate to true.
In your second loop ,the condition to stop the loop is that i must be less than 0. The range of unsigned int is 0 to 65535. so, here unsigned int i can't be less than zero. So, your condition is always true as a result the loop become infinite. Using a signed int can solve the problem.