Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing negative numbers in C

Tags:

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

like image 332
ziKmouT Avatar asked Jan 29 '16 07:01

ziKmouT


People also ask

How do you compare two negative numbers?

To compare two negative integers, the negative integer with the smaller number is greater.

How are negative numbers represented in C?

The C standard doesn't mandate any particular way of representing negative signed numbers. In most implementations that you are likely to encounter, negative signed integers are stored in what is called two's complement. The other major way of storing negative signed numbers is called one's complement.

Can you use negative numbers in C?

C and C++ are unusual amongst languages nowadays in making a distinction between signed and unsigned integers. An int is signed by default, meaning it can represent both positive and negative values.

What is negative comparing?

When negative comparison shows up, there is usually a lack of acceptance, appreciation, and love for ourselves. Instead of feeling bad about what we think is wrong with us or critical of ourselves for being judgmental, what if we took this as a cue to take care of and nurture ourselves in an authentic way?


1 Answers

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.

like image 61
skyking Avatar answered Sep 30 '22 06:09

skyking