Working with signed and unsigned 16 bit variables

Using a 16 bit binary variable it is possible to store a number in the range
0 to 65535
or
-32768 to +32767

numbers in the range 0 to 65535 are unsigned numbers in the range -32768 to +32767 are signed

The only difference in the way that signed and unsigned numbers are represented is in the interpretaion of the most significant bit of the binary value (commonly refered to as the MSB).

with unsigned numbers, when the MSB is clear it indicates a number in the range 0 to 32767 and when the MSB is set it indicates a number in the range 32768 to 65535

with signed numbers, when the MSB is clear it indicates a number in the range 0 to 32767 and when the MSB is set it indicates a number in the range -1 to -32768

here is a table of signed / unsigned 16 bit numbers together with their hexadeciaml and binary equivalents

Why bother with both signed and unsigned numbers, why not simply use signed and forget about unsigned?

In some circumstances unsigned numbers can be handled much more efficiently by the PIC processor than signed numbers. There are no circumstances where signed numbers can be handled more efficiently than unsigned numbers by the PIC processor.

Consider a situation where you need to do something 10 times. You would user a counter to count from 1 to 10. This counter would never change its meaning unless you changed the part of the program where it is used. So why would you add the extra overhead to the program of making it cope with a value that can never be less than 0.

Consider also an index into a table. Indexs are unsually offsets from the start of a table, they rarely start from the centre of a table and work to either side of the centre. An unsigned index would work one way only - forward, whereas a signed index would work forward and backwards.

I never use negative numbers, why bother having signed numbers, why not simply use unsigned and forget about signed?

Because many algorithms actually rely on the ability to use signed numbers. Programmers that wish to use these algorithms in their programs want to be able to use signed numbers without the fuss of converting unsigned numbers to signed numbers themselves, and by using the compiler to keep track of signed and unsigned variables there is far less possibility of a bug occuring.

What are the implications of useing signed and unsigned numbers together?

Even though a signed and an unsigned number may have the same binary bit patern when printed in HEX, comparing them may give unexpected results.

The value 0xffff is -1 if stored in a signed variable and 65535 if stored in an unsigned variable.

The value 0x7fff is 32767 if stored in a signed variable and 32767 if stored in an unsigned variable.

The value 0x8000 is -32768 if stored in a signed variable and +32768 if stored in an unsigned variable.

Clearly -1 is not the same as 65535. -1 is actually less than 65535. Also -32768 is not the same as +32768.

Any signed number less than 0 will be less than any unsigned number Any unsigned number greater than 32767 will be greater than any signed number

So the result of comparing a signed and an unsigned number will depend on the sign of the signed number and the range of the unsigned number.

The only real confussion will arise when debugging a program with a simulator or emulator that is unaware of the signed and unsigned use of variables. Such a debugging system may be limited to showing a number only as hex or unsigned decimal, and as already stated two hex numbers may seem identical or within a small step of each other (e.g. 0x8000 and 0x8001 or 23767 and 32768) yet be considered totally different by the running program.