To Zero and Back

Many first-time programmers rush over variable type descriptions and head full-bore into coding. That’s fine. I did it. You probably did it. But eventually you encounter code that doesn’t work properly because of negative numbers. That’s when you go back and review the concept of negative integer variable types.

Unlike floating point numbers, integers are stored in memory using plain old binary. If you can read binary (or hex), you can look at a clutch of bits and quickly divine what the value could be. In fact, nerds pride themselves on such abilities:

0110 0101 1110 0001 = 0x65E1 = 26081

The int variables you create in C are signed unless you specify the unsigned type. That means those variables can store both positive and negative values. A signed keyword exists to assert that fact, but it’s redundant for plain int, char, long, short, and long long variables.

This issue with signed variables is that at a certain point, large values become negative. This effect can get your code into trouble if you’re unaware of negative binary numbers.

Unlike reading positive binary numbers, reading a negative binary value isn’t something most nerds can do:

1000 0000 0000 0011 = 0x8003 = -32765

The far left bit in a signed integer value is the sign bit. When set, it determines that the value stored is negative. That bit doesn’t work like the minus sign in decimal math. The value above isn’t -3, it’s -32765. In fact, -3 looks like this when stored in a short signed int variable:

1111 1111 1111 1101 = 0xFFFD = -3

That representation might make no sense until you understand how binary values are counted and what happens when the bits keep flipping in the same direction.

In the following program, char variable z is signed. It starts at 1 and loops “up” to zero. It does this because after positive value 127, the signed char variable z sets its far left bit to 1, making the values negative. The next value after 127 is -128, which then steps up to zero:

#include <stdio.h>

int main()
{
    char z;

    z = 1;
    while(z != 0)
    {
        printf("%d\n",z);
        z++;
    }

    return(0);
}

Here is a snippet of the output:

1
2
3
4
...
126
127
-128
-127
...
-4
-3
-2
-1

If you modify the code, and edit Line 5 to read:

unsigned char z

Then the output looks like this (snippet):

1
2
3
4
...
252
253
254
255

The program stops at 255 because at that point, all the bits in the value flip back to zero.

The same binary values are used in both programs, but when the integer variable is signed, the output shows negative numbers.

The signed int and unsigned int values also explains why the range of integer numbers is show in two sets. Refer to Appendix D in Beginning C Programming For Dummies to view the values and ranges.

In next week’s Lesson, I explore further the concept of negative Integers and how they work.

Leave a Reply