Как компьютер хранит текст: ASCII и UTF-8

В памяти компьютера нет букв. Есть только байты — числа от 0 до 255, как мы выяснили в статьях про двоичную запись и дополнительный код. Весь текст, который вы сейчас читаете, — это последовательность чисел, плюс соглашение о том, какое число какая буква. Разберём это соглашение по шагам — от ASCII 1963 года до UTF-8, на котором работает интернет.

символ код байт H 72 01001000 I 73 01001001 72 = 64 + 8; 73 = 64 + 8 + 1 — коды отличаются на единицу, как и буквы в алфавите
Слово «HI» в памяти — это две ячейки-байта: 72 и 73. Буква — просто число, выведенное на экран как символ

Буквы — это числа

Компьютер умеет хранить и пересылать только биты. Чтобы хранить текст, нужно договориться о таблице соответствия: какое число означает какую букву. Такое соглашение называется кодировкой. Кодировка — не устройство и не программа, а просто договорённость, как азбука Морзе: «•−» означает A, потому что так договорились.

Если два компьютера договорились об одной кодировке — текст доходит без потерь. Если о разных — на экране «кракозябры»: числа те же, буквы другие.

ASCII: таблица на 128 символов

В 1963 году в США утвердили ASCII — американский стандартный код для обмена информацией. Семь бит дают 128 позиций, и каждую заняли: латинские буквы, цифры, знаки препинания и управляющие коды (перевод строки, звонок). Фрагмент таблицы:

КодДвоичныйСимвол
48001100000
6501000001A
6601000010B
9001011010Z
9701100001a
12201111010z

В таблице спрятана занятная арифметика: код цифры «0» — 48, поэтому «символ минус 48» даёт значение цифры. Большие и маленькие буквы отличаются ровно одним битом: A = 65, a = 97, разница — 32, один бит в пятом разряде. Перевод регистра в любом языке программирования — это операция ИЛИ/И над одним битом, что роднит текстовые обработки со схемотехникой из статьи о масках.

256 символов мало: UNICODE

Один байт — 256 значений: латиница помещается, а вот алфавиты кириллицы, греческого, иврита, арабского и иероглифы — уже нет. В эпоху до интернета каждую кодовую страницу изобретали отдельно, и один и тот же байт 0xD0 в одной кодировке означал «Ð», в другой — «Р». Обмениваться текстами стало невозможно.

Решение — UNICODE: единая таблица на все символы мира (более 150 000: все алфавиты, иероглифы, математические знаки, эмодзи). Каждый символ получил постоянный номер — кодовую точку. Буква «Ж» — это номер 1046, где бы она ни встретилась.

UTF-8: умная упаковка

Хранить номера UNICODE «в лоб» расточительно: латинская «A» (номер 65) поместилась бы в один байт, а если тратить четыре байта на каждый символ, английский текст распух бы вчетверо. UTF-8 решает это переменной длиной:

— Символы с номерами 0–127 (весь ASCII) — 1 байт, байты неотличимы от старого ASCII.
— Кириллица и большинство алфавитов — 2 байта.
— Иероглифы — 3 байта, редкие символы и эмодзи — 4 байта.

Длина зашита в сам первый байт: если старший бит 0 — это однобайтовый ASCII; если байт начинается с 110 — символ длиной 2 байта; 1110 — из 3. Продолжающие байты всегда начинаются с 10. Благодаря этому UTF-8 не имеет проблемы «середины символа»: случайно отрезав строку, вы всегда определите границу. Слово «Ж» в UTF-8 — это два байта: 0xD0 0x96 (номер 1046 = 0x416 упакован по схеме 110xxxxx 10xxxxxx).

Именно поэтому UTF-8 стал языком интернета: английский текст остаётся однобайтовым, всё остальное — честно закодировано, и одна кодировка покрывает всю планету.

Проверь себя

Что такое кодировка?

Соглашение о соответствии между числами и символами. Сам компьютер хранит только числа; буквы появляются лишь при выводе по договорённой таблице.

Какой бит отличает заглавную латинскую букву от строчной в ASCII?

Один бит: A = 65 (01000001), a = 97 (01100001). Разница — ровно 32, бит в пятом разряде.

Почему UTF-8 победил, хотя есть «ровные» четырёхбайтовые форматы?

Из-за переменной длины: ASCII остаётся одним байтом, граница символа восстанавливается по старшим битам, и вся таблица UNICODE покрывается без исключений.

Попробовать в симуляторе →