ziKmouT
ziKmouT

Reputation: 205

Comparing negative numbers in C

I am having a problem with a program I wrote. The program is going into a if statement whereas it should not. I have two variables:

size_t len = 5;
int    tmp = -1;

When I do :

if (tmp > len)
    ft_putstr("this is crazy");

I prints out "this is crazy whereas -1 is smaller than 5 to me ! Ok, ok. So I looked on my favorite website and saw this.

When trying:

printf("%zu", tmp) 

I see a big positive number. Ok ! This might be the reason why my program goes into the if condition above, but how can I make it not to go inside the if condition ??? thanks

Upvotes: 5

Views: 13187

Answers (2)

skyking
skyking

Reputation: 14400

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.

Upvotes: 10

Pawan
Pawan

Reputation: 1605

You have to understand the difference between different variable type. variable types such as int, unsigned, size_t etc. has different behaviour and based on that you get the results.

If you truly want to compare two numbers, they all have to be on same level (variable type) else you get unexpected results.

Following will solve your problem.

if(tmp > (int)len)
    ft_putstr("this is crazy");

As @jblixr suggested (thanks for the comment), you may want to take care of sizeof these variable types and make sure that the values are not lost while converting the values from one data type to another data type.

Upvotes: 0

Related Questions