what exactly is the difference between signed and unsigned in C?


R

radnus2004

Hi all,

I am not clear what is the difference between signed and unsigned
in C. Many say, unsigned means only +ve values and 0.

Can I use unsigned int i = -3?
What happens internally ? What conversion happens?
Also on 32 and 64bit machines what happens?

Can anybody explain?
 
Ad

Advertisements

A

Alex Fraser

I am not clear what is the difference between signed and unsigned
in C. Many say, unsigned means only +ve values and 0.

Can I use unsigned int i = -3?
Yes.

What happens internally ? What conversion happens?

Conversion of a value to any unsigned type is conceptually performed by
repeatedly adding or subtracting <maximum value for type>+1 until the result
lies between 0 and <maximum value for type> inclusive.

If UINT_MAX (defined in <limits.h>), the maximum value for an unsigned int,
is 65535, then this:

#include <stdio.h>
int main(void) {
unsigned int i = -3;
printf("%u\n", i);
return 0;
}

will output 65533, since -3 + (65535+1) = 65533.

If UINT_MAX = 4294967295 (common on 32- and 64-bit platforms), the output
will be 4294967293.
Also on 32 and 64bit machines what happens?

The only difference the platform makes to the above conversion is due to the
possible difference in UINT_MAX (assuming the compiler is conforming). Is
that what you were asking?

Alex
 
M

Malcolm

I am not clear what is the difference between signed and unsigned
in C. Many say, unsigned means only +ve values and 0.

Can I use unsigned int i = -3?
What happens internally ? What conversion happens?
Also on 32 and 64bit machines what happens?

Can anybody explain?
Almost all computers use two's complement notation. This means that to
negate an integer you invert the bits, and then add one, losing the overflow
if any. so 1 becomes 11111110 and then 11111111 (all bits set). Zero becomes
11111111 and then overflows to 00000000, which is correct, -0 equals 0.

Internally the processor often has no concept of negative numbers. This is
because adding and throwing away the overflow, in two's complement, is
exactly the same as negating and subtracting.

However the C standard doesn't guarantee that two's complement will be used.
So we have the situation that trying to express -3 as an unsigned integer is
probably going to produce its twos complement value 11111101 (right extend
the ones to sixteen of thirty-two bits instead of eight), which is a
largeish unsigned value. However you cannot be sure of this, and sometimes
you might manage to trigger an internal trap. So from the point of view of
the C stnadard it is actually better to forget all you know about two's
complement values, and just assume that trying to express a negative integer
as an unsigned is illegal.
 
K

Keith Thompson

Malcolm said:
However the C standard doesn't guarantee that two's complement will be used.
So we have the situation that trying to express -3 as an unsigned integer is
probably going to produce its twos complement value 11111101 (right extend
the ones to sixteen of thirty-two bits instead of eight), which is a
largeish unsigned value. However you cannot be sure of this, and sometimes
you might manage to trigger an internal trap. So from the point of view of
the C stnadard it is actually better to forget all you know about two's
complement values, and just assume that trying to express a negative integer
as an unsigned is illegal.

Conversion from signed to unsigned is well-defined in C. It's defined
in terms of values, not in terms of the underlying representation.

Conceptionally, converting a signed value to "unsigned int" is done by
repeatedly or subtracting UINT_MAX+1 until the result is within range.
For example, assuming 16-bit int, (unsigned)-3 is computed by adding
65536 to the mathematical value, yielding 65533.

It happens that this is easy to implement on a 2's-complement system,
but the same requirement applies to other systems (though they're
rare).
 
N

Novitas

To answer your question a bit more expansively, unsigned and signed
ints are treated differently in terms of what condition flags are used
to evaluate them per C relational operators.

In plain english this means that a>b may have different answers
depending on whether a and b are signed, unsigned, or mixed.
 
Ad

Advertisements

O

Old Wolf

Novitas said:
To answer your question a bit more expansively, unsigned and signed
ints are treated differently in terms of what condition flags are used
to evaluate them per C relational operators.

What are "condition flags".
In plain english this means that a>b may have different answers
depending on whether a and b are signed, unsigned, or mixed.

That's not very expansive :)
If a and b are both signed, or both unsigned, there is no confusion.
If one is signed and one isn't, then the signed one is promoted to
unsigned (via the process described by Keith Thompson in this thread).

The same goes for the other arithmetic binary operators
(but not the bitwise binary operators).
 
Ad

Advertisements


Top