I recall the math class where negative numbers were introduced. I was appalled. From *Star Trek*, I easily accepted the concept of antimatter, but the notion of negative values deeply offended me.

As I learned about computers, negative binary numbers blew me away. In a clutch of bits, which is essentially how values on a computer are stored, how can you have something negative? I mean, binary is just one and zero, right? Where is the negative?

The answer is the *sign bit*.

In a binary value, the left-most bit is the sign bit — for *signed* integer values. The *unsigned* integer type values treat the bit as part of the number. But for a *signed* value, the bit is 0 for a positive value or 1 for a negative value, as crudely illustrated in Figure 1.

In Figure 1, the first value shown is -1, binary `11111111`

for a *signed* byte-sized (*char*) integer value. For the *unsigned* data type, the value shown is 255. The latter value makes more sense to me. Therefore, to best illustrate how this nonsense works, a program is in order.

### 2021_04_03-Lesson-a.c

#include <stdio.h> int main() { signed char a = 0; int x; for( x=0; x<256; x++ ) { printf("%d\n",a); a++; } return(0); }

This code loops through char values from 0 to 256. But because variable `a`

is *signed*, once it huts the value where the sign bit is flipped from 0 to 1, negative values are output. Here is the interesting part of that output:

`123`

124

125

126

127

-128

-127

-126

-125

After 127 (binary `01111111`

) the next value is -128 (binary `10000000`

). Below, I’ve modified the code to include my *binbin()* function, which is showcased in my C books for outputting binary values:

### 2021_04_03-Lesson-b.c

#include <stdio.h> char *binbin(unsigned char n) { static char bin[9]; int x; for(x=0;x<8;x++) { bin[x] = n & 0x80 ? '1' : '0'; n <<= 1; } bin[x] = '\0'; return(bin); } int main() { signed char a = 0; int x; for( x=0; x<256; x++ ) { printf("%d\t%s\n",a,binbin(a)); a++; } return(0); }

The code runs the same, but with an additional column in the output. Again, here is the interesting part:

`123 01111011`

124 01111100

125 01111101

126 01111110

127 01111111

-128 10000000

-127 10000001

-126 10000010

-125 10000011

As soon as the 8th bit (for a *char*) flips, the values output are negative. Further, they flow upward as variable `a`

increments. Eventually, the value returns to zero.

The sign bit is significant for *signed* integer variables. In fact, you can force-flip the bit so that values turn negative, as demonstrated in the following code:

### 2021_04_03-Lesson-c.c

#include <stdio.h> char *binbin(unsigned char n) { static char bin[9]; int x; for(x=0;x<8;x++) { bin[x] = n & 0x80 ? '1' : '0'; n <<= 1; } bin[x] = '\0'; return(bin); } int main() { signed char a = 0; int x; for( x=0; x<256; x++ ) { a |= 0x80; printf("%d\t%s\n",a,binbin(a)); a++; } return(0); }

This code is identical to the preceding example, save for a new Line 24: `a |= 0x80`

. This statement sets the first bit in the byte to 1, which makes all the output negative. Again, the same chunk of output from the sample run as shown earlier:

`-5 11111011`

-4 11111100

-3 11111101

-2 11111110

-1 11111111

-128 10000000

-127 10000001

-126 10000010

-125 10000011

With the sign bit set, the first part of the output shows negative values, from -128 on up to -1. Then the loop starts over again at -128.

By the way, `10000000`

is interpreted as -128 and not “negative zero.” Unlike other programming languages, C lacks an equivalent for negative zero. I explore this notion in next week’s Lesson.