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.
Related
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 was running the code example below, initially trying to print a character array backwards where count represented the number of characters in the array. Everytime I ran the for loop, i was not initalized to count - 1 instead it was initialized to some very large number. But outside the loop, i is properly initalized to 4. I can't explain why this is happening.
size_t count {5};
size_t i {count - 1UL}; // i is initalized to 4
for(size_t i {count - 1}; i >= 0UL; --i) {
std::cout << i << std::endl;
} // infinite loop, i is initalized to 18446744073709141874
An "unsigned" integer does not have a sign and is always nonnegative. If you do --i on i = 0 then you will get the maximum value of std::size_t.
Do this instead:
// iterates from (count - 1) to 0
for (std::size_t i = count; i--;)
So how does this work? i-- is the postfix decrement operator, which returns the prior value of i. This way, the loop condition is actually comparing count, ..., 1 to zero, while in the loop we get count - 1, ..., 0.
A more generalized version of this idiom is sometimes called the --> operator:
// iterates from (high - 1) to low
for (std::size_t i = high; i-- > low;)
Firstly, i in the outer scope is unused and shaded, secondly an unsigned integer is always greater than or equal to 0. You could have your compiler detect these if only you turned on your compiler warnings:
<source>:7:38: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
7 | for(std::size_t i {count - 1}; i >= 0UL; --i) {
| ~~^~~~~~
<source>:5:17: error: unused variable 'i' [-Werror=unused-variable]
5 | std::size_t i {count - 1UL}; // i is initalized to 4
|
Solution:
for (unsigned long long i = 4ull; i != -1ull; --i) {
std::cout << i << '\n';
}
std::size_t is unsigned integer type. So values of the type never can be negative.
Rewrite the loop like
std::size_t i {count - 1};
do
{
std::cout << i << std::endl;
} while ( i-- );
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.
I have this simple program:
// Include libraries
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Include locals
// Start
#define NUMBER 600851475143
int main(int argc, const char* argv[])
{
long long int ans = 0;
long long int num = NUMBER;
vector<int> factors;
do
{
// Get lowest factor
for (int i = 1; i <= num; ++i)
{
if (!(num % i))
{
factors.push_back(i);
num /= i;
break;
}
}
} while (num > 1);
cout << "Calculated to 1.\n";
int highestFactor = numeric_limits<int>::min();
for (int i = 0; i < factors.size(); ++i)
{
if (factors[i] > highestFactor)
{
highestFactor = factors[i];
}
}
ans = highestFactor;
cout << ans << endl;
return EXIT_SUCCESS;
}
compiling with g++ -O2 -c -o prob3.o prob3.cpp proved successful, but when I ran it I saw nothing and it just kept running and I had to Ctrl-C (force-kill) it in the end. When I try to add
int main(int argc, const char* argv[])
{
cout << "Test\n";
to the program, Test didn't get printed too. It's like my program is not executed at all.
Any help or advice is appreciated!
Solution
I forgot prime numbers started at 2. Change for (int i = 1 to for (int i = 2.
Those nested loops are going to loop forever. The inner for loop will only ever execute once because of the break so it will only ever do num /= 1. That means num never decreases and so num > 1 will never be false. I suppose you just need to wait longer!
The reason you're not seeing "Test" is probably because you haven't flushed the output. Try:
std::cout << "Test" << std::endl;
Your program is simply running. It takes a long time to execute.
For the cout << "Test\n";, it's a matter of the cout stream not being flushed: what you wrote to the stream is still in your program memory and not yet flushed to the system to be printed.
Have you tried to start your for condition from 2? The module function doesn't have sense if start from 1.
if (!(num % i))
Num / 1 give 0, so you're not enter in the if condition
Your loop is an infinite loop. The first factor you find is 1 (since num % 1 is 0) and as such you divide num by 1 which results in num which re-enters the for loop, which does the same again and again.
Also with this fixed (initialize i in the loop with 2), your inner for loop is most likely an infinite loop and/or causing UB. Otherwise (as the others stated) it is "just" running very long. For the case where it is different (assuming most common platforms here). This depends on the value you are trying to factor, if the first factor is smaller than std::numeric_limits<int>::max() then this does not apply. Lets call those primes BIGPRIME (600851475149 would be a good example).
long long int is at least 64bit in size. int is unlikely to be bigger than 32bit on most platforms, so when it is not bigger on your platform it can only go up to std::numeric_limits<int>::max() which is (again assuming the common 32bit platform here) 2147483647 which is in turn promoted in the comparison to long long int but keeps its value, which is always smaller than BIGPRIME. Always increasing i does never get anywhere, and once you are at max() you enter UB land as signed integers don't wrap in C++. Your code might infinite loop there, or do some things like recording -1 as a valid factor, or make you pregnant.
You can easily observe that by adding some
if( 0 == (i%100000000)){ std::cout << i << std::endl; }
into the for loop.
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];