Omkant
Omkant

Reputation: 9204

how signed and unsigned integers are stored in c?

I am trying to run the following code but confused with what's happening here:

int main()
{
 /* 
    a = -1; 
    b = 0xffffffff; 
 */
if(-1 == 0xffffffff )
        printf("-1 is equal to maximum\n");
else
        printf(" -1 is not equal to maximum\n");

if(0xff < -1)
        printf(" Less than -1 \n");
if(0xff < 0xffffffff)
        printf(" Less than maximum\n");

I tried with commented section as well and replaced -1 with "a" and 0xffffffff with "b" but the result is same .

It's 32 bit system so i have taken integer size 4 bytes.

My Output is :

-1 is equal to maximum
 Less than maximum

If -1 is equal to maximum then it should execute both of the last two if statements. But it's not happening. Why?

Upvotes: 6

Views: 13554

Answers (4)

Sandesh Kobal
Sandesh Kobal

Reputation: 920

In C/C++, negative numbers are stored in 2's compliment format and Most Significant Bit(MSB) acts as a sigh indication.

MSB 1 means -ve and MSB 0 means +ve. 1xxxxxxxxxx is -ve number and 0xxxxxxxxxx means +ve. In 1xxxxxxx the "xxxxxx" is 2's compliment of a number. And in 0xxxxxx the "xxxxx" is actual binary representation of a number.

Compiler interpret number as -ve if MSB(sign bit) is 1 and understands the number has to be the two's compliment.

First lets see what is 2's compliment:

2's compliment is negating an actual number(all bits) and then adding 1.

decimal 1 = 00000001

~ decimal 1 = 11111110

2's compliment of decimal 1 = 11111111 (F hex)

so -1 becomes = (1) 111111111111111

(1) is a MSB indicating -ve number the rest is the 2's compliment of a number.

thus -1 = 0xFFFFFFFF

You can try out printing binary representation of some -ve numbers and comparing the 2's compliment of binary representation of a number.

Upvotes: 3

Steve Jessop
Steve Jessop

Reputation: 279215

First thing, the results you see have nothing to do with the bit representation of signed integers, although they do have to do with the size.

When converted to unsigned, the value -1 is converted to the max value of the destination type. That's why -1 == 0xffffffff. The bit representation of -1 doesn't affect anything.

0xff < -1 is false because both values are signed int: 255 on the left and -1 on the right.

Finally, the reason -1 is converted to unsigned in the first comparison is that 0xffffffff is too big for int on your implementation (and for that matter on most implementations). However, it does fit in an unsigned int (again on your implementation, and on most implementations other than those for 16 bit machines). In order to compare an unsigned int against a signed int, C converts the signed int to unsigned. This gives surprising results (including the surprise that -1 is somehow equal to a positive number), which is why most style guides tell you to avoid mixing signed and unsigned types. But it's too late to change the language.

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 476930

I'll quote this from C++; I think it's the same for C:

The literal -1 is always a signed int.

The literal 0xff is a signed int, but 0xffffffff is an unsigned int.

In comparisons of mixed signs, both operands are converted to unsigned, explaining all your results.

Here's the rule about the types of naked integral literals (i.e. without type suffix) from C++11, table 6:

  • Decimal literals are of the smallest type among int, long int or long long int, whichever fits.

  • Hexadecimal literals are of the smallest type among int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, whichever fits.

To spell it out again:

  • In your first comparison, both sides are converted to unsigned int, giving the value 0xFFFFFFFF.

  • In the second comparison, both terms are signed integers, and the left term is 255 and the right term is -1.

  • In the third comparison, both terms are converted to unsigned int.


Observe that we never needed to worry about hardware implementations of signedness for this question. The only relevant platform-dependent value is the size of int, which we used when we asserted that 0xffffffff does not fit into an int but does fit into an unsigned int.

Upvotes: 5

Aaron Digulla
Aaron Digulla

Reputation: 328536

0xffffffff is equal to -1 since the int type has only four bytes and the two-complement of -1 is 0xffffffff in memory (-1 == (~1) + 1). So the compiler has no way to tell -1 and 0xffffffff apart - there simply isn't room for that in memory.

0x000000ff is equivalent to 255 which is bigger than -1, so the last two ifs won't get executed.

What might be confusing you is this:

char c = 0xff;
if( c == -1 ) {
     printf("char 0xff is -1");
}

In this case, I compare a char with an int, so the compiler will have to expand the 8-bit char type. Since char is signed, the sign (uppermost bit) will be preserved and you'll get -1 (int).

interactive demo on codepad

This is an example why you need to be careful when mixing signed/unsigned types and types of different widths.

Upvotes: 0

Related Questions