Numbers are just bits

A byte is 8 bits, and each bit is 0 or 1. Read as a plain binary number, 8 bits can hold 2 to the power 8 = 256 different patterns, so an unsigned char stores 0 to 255.

00000000 = 0
00000101 = 5     (4 + 1)
11111111 = 255   (128+64+32+16+8+4+2+1)

So what happens if you add 1 to 255? There is no ninth bit to carry into. For unsigned types, C defines the answer: the value wraps around modulo 256, so you get 0. Like a car odometer rolling over.

unsigned char u = 255;
u = u + 1;   // u is now 0

(Pedantic detail: u + 1 is actually computed as an int, giving 256, and storing 256 back into an unsigned char keeps only the low 8 bits. Same result, and it is fully defined.)

Signed types are different. Overflowing a signed int is undefined behaviour: the standard makes no promise at all, and optimising compilers really do assume it never happens. Many machines will happen to wrap to a negative number, but you must not rely on it. Use unsigned types when you want wrap-around.

Binary gets long fast, so programmers write bytes in hexadecimal: base 16, digits 0-9 then a-f. One hex digit is exactly 4 bits, so one byte is always two hex digits. 255 is ff, 16 is 10. Print hex with %x, and an unsigned value with %u.

Try it yourself

Edit it. Break it. Run it again.
#include <stdio.h>

int main(void) {
    unsigned char u = 250;
    for (int i = 0; i < 8; i++) {
        printf("%u (hex %x)\n", u, u);
        u = u + 1;
    }
    printf("255 in hex is %x, 4096 in hex is %x\n", 255, 4096);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Your turn

Type it yourself. That is the whole trick.

1Odometer rollover

Start an unsigned char called fuel at 250. Add 10 to it, then print it with %u. Predict the answer before you run it. The output should be: 4

#include <stdio.h>

int main(void) {
    unsigned char fuel = 250;
    // add 10, then print
    printf("%u\n", fuel);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

2Speak hex

Print the numbers 10, 15, 16 and 255, each on its own line, as decimal = hex, like this:

  • 10 = a
  • 15 = f
  • 16 = 10
  • 255 = ff

Use a format code for the hex part rather than typing it.

#include <stdio.h>

int main(void) {
    printf("%d = %d\n", 10, 10);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.