See docs for size_t
:
std::size_t
is the unsigned integer type of the result of the sizeof
operator
(Emphasis mine.)
Furthermore, string::length
returns a size_t
too1.
But even if that were not the case, when comparing signed values to unsigned values, the signed value is converted to unsigned before the comparison, as explained in this answer.
(size_t)0 - 2
will underflow as size_t
is unsigned and therefore its minimum value is zero resulting in a large number which is usually2 either 232-2 or 264-2 depending on the processor architecture. Let's go with the latter, then you will get 18,446,744,073,709,552,000 as result.
Now, looking at the result of 0 <= 18446744073709552000
you can see that zero is clearly less than or equal to 18.4 quintillion, so the loop condition is fulfilled. In fact the loop is not infinite, it will loop exactly 18,446,744,073,709,552,001 times, but it's true you will probably not want to wait for it to finally reach its finishing point.
The solution is to avoid the underflow by comparing i + y <= x
instead of i <= x - y
3, i.e. i + 2 <= qaz.length()
. You will then have 2 <= 0
which is false.
1: Technically, it returns an std::allocator<char>::size_type
but that is defined as std::size_t
.
2: To be exact, it is SIZE_MAX - (2 - 1)
i.e. SIZE_MAX - 1
(see limits). In terms of numeric value, it could also be 216-2 - such as on an ATmega328P microcontroller - or some other value, but on the architectures you get on desktop computers at the current point in time it's most likely one of the two I mentioned. It depends on the width of the std::size_t
type. If it's X bits wide, you'd get 2X-n for (size_t)0 - n
for 0<n<2X. Since C++11 it is however guaranteed that std::size_t
is no less than 16 bits wide.
3: However, in the unlikely case that your length is very large, specifically at least the number calculated above with 2X-2 or larger, this would result in an overflow instead. But in that case your whole logic would be flawed and you'd need a different approach. I think this can't be the case anyway because std::ssize
support means that string lengths would have to have one unused bit to be repurposed as sign bit, but I think this answer went down various rabbit holes far enough already.