A6SE
A6SE

Reputation: 270

How does C store negative numbers in signed vs unsigned integers?

Here is the example:

#include <stdio.h>

int main()
{
    int x=35;
    int y=-35;
    unsigned int z=35;
    unsigned int p=-35;
    signed int q=-35;
    printf("Int(35d)=%d\n\
Int(-35d)=%d\n\
UInt(35u)=%u\n\
UInt(-35u)=%u\n\
UInt(-35d)=%d\n\
SInt(-35u)=%u\n",x,y,z,p,p,q);

    return 0;
}

Output:

Int(35d)=35
Int(-35d)=-35
UInt(35u)=35
UInt(-35u)=4294967261
UInt(-35d)=-35
SInt(-35u)=4294967261

Does it really matter if I declare the value as signed or unsigned int? Because, C actually only cares about how I read the value from memory. Please help me understand this and I hope you prove me wrong.

Upvotes: 5

Views: 51758

Answers (5)

John Bode
John Bode

Reputation: 123578

Representation of signed integers is up to the underlying platform, not the C language itself. The language definition is mostly agnostic with regard to signed integer representations. Two's complement is probably the most common, but there are other representations such as one's complement and signed magnitude.

In a two's complement system, you negate a value by inverting the bits and adding 1. To get from 5 to -5, you'd do:

5 == 0101 => 1010 + 1 == 1011 == -5

To go from -5 back to 5, you follow the same procedure:

-5 == 1011 => 0100 + 1 == 0101 == 5

Does it really matter if I declare the value as signed or unsigned int?

Yes, for the following reasons:

  1. It affects the values you can represent: unsigned integers can represent values from 0 to 2N-1, whereas signed integers can represent values between -2N-1 and 2N-1-1 (two's complement).

  2. Overflow is well-defined for unsigned integers; UINT_MAX + 1 will "wrap" back to 0. Overflow is not well-defined for signed integers, and INT_MAX + 1 may "wrap" to INT_MIN, or it may not.

  3. Because of 1 and 2, it affects arithmetic results, especially if you mix signed and unsigned variables in the same expression (in which case the result may not be well defined if there's an overflow).

Upvotes: 8

Jite
Jite

Reputation: 4368

An unsigned int and a signed int take up the same number of bytes in memory. They can store the same byte values. However the data will be treated differently depending on if it's signed or unsigned.

See http://en.wikipedia.org/wiki/Two%27s_complement for an explanation of the most common way to represent integer values.

Since you can typecast in C you can effectively force the compiler to treat an unsigned int as signed int and vice versa, but beware that it doesn't mean it will do what you think or that the representation will be correct. (Overflowing a signed integer invokes undefined behaviour in C).

(As pointed out in comments, there are other ways to represent integers than two's complement, however two's complement is the most common way on desktop machines.)

Upvotes: 4

丁东阳
丁东阳

Reputation: 59

#include <stdio.h>

int main(){
    int x = 35, y = -35;
    unsigned int z = 35, p = -35;
    signed int q = -35;

    printf("x=%d\tx=%u\ty=%d\ty=%u\tz=%d\tz=%u\tp=%d\tp=%u\tq=%d\tq=%u\t",x,x,y,y,z,z,p,p,q,q);
}

the result is: x=35 x=35 y=-35 y=4294967261 z=35 z=35 p=-35 p=4294967261 q=-35 q=4294967261

the int number store is not different, it stored with Complement style in memory,

I can use 0X... the 35 in 0X00000023, and the -35 in 0Xffffffdd, it is not different you use sigend or unsigend. it only output with different sytle. The %d and %u is not different about positive, but the negative the first position is sign, if you output with %u is 0Xffffffdd equal 4294967261, but the %d the 0Xffffffdd can be - 0X00000023 equal -35.

Upvotes: 1

glglgl
glglgl

Reputation: 91139

Does it really matter if I declare the value as signed or unsigned int?

Yes.

For example, have a look at

#include <stdio.h>

int main()
{
    int a = -4;
    int b = -3;
    unsigned int c = -4;
    unsigned int d = -3;
    printf("%f\n%f\n%f\n%f\n", 1.0 * a/b, 1.0 * c/d, 1.0*a/d, 1.*c/b);
}

and its output

1.333333
1.000000
-0.000000
-1431655764.000000

which clearly shows that it makes a huge difference if I have the same byte representation interpreted as signed or unsigned.

Upvotes: 3

Freddie Chopin
Freddie Chopin

Reputation: 8860

The most fundamental thing that variable's type defines is the way it is stored (that is - read from and written to) in memory and how are the bits interpreted, so your statement can be considered "valid".

You can also look at the problem using conversions. When you store signed and negative value in unsigned variable it gets converted to unsigned. It so happens that this conversion is reversible, so signed -35 converts to unsigned 4294967261, which - when you request it - can be converted to signed -35. That's how 2's complement encoding (see link in other answer) works.

Upvotes: -1

Related Questions