The problem here is that you are trying to compare something that is unsigned with something that is signed. This means that there's an implicit conversion involved before the actual conversion is done. In this case the signed is converted to unsigned (which is normally not what one would want - therefore many compilers have options to display warning when this is done).
To do it more correct in a sloppy way you would write:
if( (int)tmp > (int)len )
however this ignores the fact that size_t
could have values that are too large for int
. To be strict one would have to handle that the range of int
combined with the range of size_t
could be larger than any available type. This means that you would have to handle this in two cases, so you would use the fact that if tmp<0
then tmp<len
(mathematically, since len>=0
). So for example mathematically tmp<len
would be written as tmp<0 || tmp<len
. And the opposite would be tmp>=0 && tmp >= len
. You should therefore write:
if( tmp >= 0 && tmp > len )
Note that then the conversion is not a problem, tmp
could after the first check be converted to unsigned without change of value, different ranges of int
and size_t
are not a problem either as the smaller is converted to wider range before comparison.
The only problem left is that if you have enabled warnings about signed-unsigned comparison (to detect these kind of mistakes) it would still warn. To take care of that you would need to explicitely type cast it, but we know that conversion to unsigned doesn't change tmp
once we checked that tmp>=0
. So to avoid warnings you would write:
if( tmp >= 0 && (unsigned)tmp > len) )
the (unsigned)
is because tmp
is an int
, you need to respect the type when converting to unsigned if tmp
were of another type.