Consider the following code snippet (for demonstration purposes):
#include <bits/stdc++.h>
using namespace std;
int main(){
char s[] = "x";
for (int i=0; i<=strlen(s)-4; i++){
cout << s[i];
}
return 0;
}
You'd expect the for
to never loop at all, since the initial value of i
(0) would be higher than that of strlen(s)-4
(-3) right? But no, it becomes an infinite loop... You can test it yourself. Here are the watches from a random state in the loop:
After searching about this issue a bit, I read that it isn't a good practice to put strlen()
into a for
as a condition, since it takes time to compute it each loop. So yes, from now on I will avoid this approach, either by storing the value into a variable beforehand, or by checking if I reached the end using s[i]
.
But... What if whatever causes this occurs in some other context that doesn't involve strlen()
? I'd like to understand why this happens in the first place, so I can better watch out for it.
So could somebody help me understand what is going on here? :)
Strlen returns size_t (unsigned value), so 1 — 4 = INT_MAX — 2(or -3). That's why it seems it is an infinite loop.
Ohhhh, right.
Who would have thought that the
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
you get with such code is actually useful, since it may sometimes lead to something you'd not expected? :))Cheers, mate!
strlen
returns size_t which is basically a type of unsigned integer. In unsigned integers, -3 is actually INT_MAX-2, which is obviously greater than most values of i. That is why your loop runs for a very long time.You can fix it easily by type casting it to a signed integer.
i<=(int)strlen(s) - 4
Also beware that strlen() is of O(n) complexity. Putting it in for loop condition may result in TLE
Just to add a little clarity, your heading says "Weird strlen() behaviour in C++ for loops", but, strlen() is not a C++ function. It is a C function incorporated into C++ with the help of STL. For strict C++ implementation, you should be using std::string. The std::string::size() method is O(1) in comparison to O(N) of strlen(). Like ahshafi mentions above, you could prevent a possible TLE, as you have strlen() involved as a loop condition.