The C Path — learn C, visually

🧮 Foundations — Before C

Text: ASCII, Unicode & UTF-8

⏱ 12 min · free interactive lesson · quizzes, visualizations & a real compiler

▶ Open the interactive lesson — free, no signup
Why you're learning this

That garbled text you've surely seen — an apostrophe showing up as ’, an emoji reduced to ??? — happens when two programs disagree about which numbers stand for which letters. After this lesson you'll know exactly how plain English, accents, and emoji travel as bytes, and you'll be armed against a trap that bites almost every new C programmer: one byte is not one character.

Computers only store numbers — so what is the letter 'A'? It's just the number 65, by agreement. That agreement is called a character encoding, and it's the bridge between bytes and human text.

ASCII: the original deal (1963)

ASCII assigns 0–127 to English letters, digits, punctuation, and control codes. The layout is delightfully hackable:

ascii.c
#include <stdio.h>

int main(void) {
    char c = 'A';
    printf("'%c' is %d\n", c, c);        /* chars ARE numbers  */
    printf("'%c' + 1 = '%c'\n", c, c + 1);
    printf("'7' - '0' = %d\n", '7' - '0');   /* digit trick     */
    printf("'Q' | 0x20 = '%c'\n", 'Q' | 0x20); /* lowercase bit */
    return 0;
}
terminal
$ gcc ascii.c -o ascii && ./ascii
'A' is 65
'A' + 1 = 'B'
'7' - '0' = 7
'Q' | 0x20 = 'q'

🧠 Checkpoint: In C, what does '5' - '0' evaluate to?

  • 5
  • 53
  • '5'
  • undefined
Show answer

5 — '5' is ASCII 53 and '0' is 48; 53 − 48 = 5. This subtraction trick converts any digit character to its numeric value.

Unicode: one number for every character ever

ASCII has no é, no 中, no 🎉. Unicode fixes this by assigning a code point to every character in every language — over 150,000 so far, written like U+1F600. But code points are abstract numbers; we still need to store them as bytes. Enter UTF-8, the encoding that won the internet:

Type below and watch each character become bytes:

This spot has an interactive enc widget — open the interactive lesson to play with it.

🧠 Checkpoint: How many bytes does the emoji 🙂 take in UTF-8?

  • 1
  • 2
  • 3
  • 4
Show answer

4 — Emoji live at high code points (U+1F642), which need the 4-byte UTF-8 pattern 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.

⚠️

For C programmers: a char is one byte, not one character. strlen("héllo") returns 6, not 5, because é takes two bytes in UTF-8. Keep "bytes" and "characters" separate in your head forever.

🧠 Checkpoint: Why is UTF-8 backwards-compatible with ASCII?

  • It isn’t
  • Bytes 0–127 encode exactly the ASCII characters
  • It stores a translation table first
  • ASCII files get converted on load
Show answer

Bytes 0–127 encode exactly the ASCII characters — UTF-8 was designed (on a placemat, by Ken Thompson & Rob Pike — the same folks behind Unix and UTF-8’s sibling Plan 9) so single bytes 0–127 mean the same as ASCII.

▶ Practice this lesson interactively (with live gcc)