Computers store signed integers in two's complement. The highest bit counts as negative: in 8 bits it is worth -128 instead of +128. So 11111111 is -128 + 127 = -1, and 10000000 is -128.
Two's complement
#include <stdio.h>
void show(signed char x) {
unsigned char bits = (unsigned char)x;
printf("%4d = ", x);
for (int i = 7; i >= 0; i--) printf("%d", (bits >> i) & 1);
printf("\n");
}
int main(void) {
show(5);
show(-5);
show(-1);
show(-128);
show(127);
return 0;
}To negate a number: flip every bit, then add 1. 5 is 00000101; flipping gives 11111010; adding 1 gives 11111011, which is -5. The trick makes addition simple: the same adder circuit works for positive and negative numbers.
The bits of x are read through an unsigned char, which has no sign, so you see the raw pattern.
Wrapping round and overflowing
#include <stdio.h>
#include <limits.h>
int main(void) {
unsigned char small = 0;
small = small - 1;
printf("unsigned char 0 - 1 = %d\n", small);
unsigned int big = 0;
big = big - 1;
printf("unsigned int 0 - 1 = %u\n", big);
int x = INT_MAX;
printf("INT_MAX = %d\n", x);
x = x + 1; // signed overflow: a bug
printf("%d\n", x);
return 0;
}- Unsigned numbers wrap round, as C promises: 0 - 1 gives the largest value (255 for 8 bits, 4294967295 for 32), and 255 + 1 gives 0.
- Signed overflow is a bug:
INT_MAX + 1has no right answer. In compiled C it usually wraps to a large negative number, silently; StepVioz stops the program and says what happened.
| 8 bits | unsigned | signed (two's complement) |
|---|---|---|
| 00000000 | 0 | 0 |
| 01111111 | 127 | 127 |
| 10000000 | 128 | -128 |
| 11111111 | 255 | -1 |
Use a bigger type. If a result can exceed about 2 billion (a sum of many marks, a factorial, money in paisa), use long long. It holds numbers up to about 9.2 × 10¹⁸.
Quick check
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.