Байты и биты: что нужно знать об их порядке

Байты и биты — единицы, в которых компьютер хранит и обрабатывает данные. Когда число или структура занимает несколько байтов, важен порядок байтов (endianness): в какой последовательности они записаны в памяти или передаются по сети. От этого зависят совместимость форматов, сетевые протоколы и отладка. В статье — что такое бит и байт, откуда взялись названия little-endian и big-endian, как байты распределяются в памяти, наглядный пример и что полезно знать программисту.
Содержание
- Единицы измерения: бит и байт
- Откуда взялся порядок байтов (endianness)
- Что такое порядок байтов
- Зачем это нужно
- Как байты лежат в памяти
- Пример: число в памяти
- В программировании
- Выводы
Единицы измерения: бит и байт
Бит (от англ. binary digit — «двоичная цифра») — минимальная единица информации. Он принимает одно из двух значений: 0 или 1. Бит достаточен, чтобы различить два равновероятных варианта: да/нет, истина/ложь, включено/выключено.
Байт — группа из 8 битов. Один байт может представить 256 значений (от 0 до 255). В байтах измеряют объём памяти, размер файлов и длину данных в протоколах. Исторически размер байта закрепился как 8 бит; в коде и документации «байт» почти всегда означает именно 8 бит.
Крупные единицы получают умножением на 1024 (в двоичной системе) или иногда на 1000 (в маркетинге и части стандартов): килобайт (KB), мегабайт (MB), гигабайт (GB), терабайт (TB).
Рис. 1 — Бит, байт и кратные единицы
Откуда взялся порядок байтов (endianness)
Термины big-endian и little-endian пришли из статьи Дэнни Коэна (1980) о порядке байтов в сетевых сообщениях. Коэн использовал аллегорию из «Путешествий Гулливера»: война между теми, кто разбивает яйца с большого конца (big endians), и теми, кто — с маленького (little endians). Так в IT закрепились названия:
- Big-endian — «старший конец впереди»: старший (наиболее значащий) байт записывается по младшему адресу памяти.
- Little-endian — «младший конец впереди»: младший (наименее значащий) байт записывается по младшему адресу.
Оба варианта допустимы; выбор исторически закреплён за архитектурой процессора и протоколами (например, в сетях часто используют big-endian как «network byte order»).
Рис. 2 — Два основных порядка байтов
Что такое порядок байтов
Порядок байтов — это последовательность, в которой байты многобайтового значения (числа, поля структуры) записываются в память или передаются по каналу связи. Один и тот же 32-битный или 64-битный код в разных системах может храниться в разном порядке байтов; если не договориться (или не преобразовать при обмене), данные будут искажены.
В многобайтовом числе различают:
- MSB (most significant byte) — старший значащий байт; он даёт больший вклад в значение числа.
- LSB (least significant byte) — младший значащий байт; наименьший вклад.
Аналогично для битов внутри байта: MSb — старший бит, LSb — младший. Порядок байтов говорит о том, в каком порядке по возрастанию адреса идут MSB и LSB.
Рис. 3 — MSB и LSB в 4-байтовом значении
Зачем это нужно
Понимание порядка байтов нужно, когда:
- Пишете или читаете бинарные форматы (файлы, заголовки протоколов): в спецификации обычно указано, в каком порядке идут байты.
- Обмениваетесь данными по сети: во многих протоколах (TCP/IP и др.) принят big-endian («network byte order»); хост на x86 хранит числа в little-endian — при отправке/приёме их преобразуют.
- Отлаживаете память или дампы: видишь байты по адресам — нужно понимать, как они складываются в число.
- Работаете с разными платформами: ARM, x86, сетевой формат — порядок может отличаться; без учёта этого легко получить несовместимость.
Как байты лежат в памяти
Память адресуется побайтово: у каждого байта свой адрес. Многобайтовое значение занимает несколько подряд идущих ячеек. Порядок байтов определяет, какой байт числа лежит по младшему адресу, какой по следующему и т.д.
Обратный порядок (little-endian)
Little-endian — порядок «от младшего к старшему»: младший байт (LSB) хранится по младшему адресу, старший (MSB) — по старшему. Это привычный порядок для x86 (Intel, AMD) и многих ARM-конфигураций. Иногда его неформально называют «интеловским».
Плюс для процессора: при росте разрядности операнда (8 → 16 → 32 → 64 бит) первый байт по младшему адресу не меняется — совпадает с младшим байтом более длинного значения. Удобно для совместимости и части низкоуровневых операций.
Little-endian используется в PCI, USB, в таблице разделов GPT, во многих форматах под x86. В сетевых протоколах чаще применяется big-endian; данные при отправке/приёме конвертируют.
Рис. 4 — Расположение байтов в little-endian
Прямой порядок (big-endian)
Big-endian — порядок «от старшего к младшему»: старший байт (MSB) по младшему адресу, затем следующие по убыванию значимости. Так мы обычно записываем числа арабскими цифрами: слева направо от старшего разряда к младшему.
Big-endian принят как порядок байтов в сети (network byte order): заголовки TCP/IP и многие протоколы верхнего уровня используют его. Так же хранят данные ряд процессоров (например, старые Motorola 68000, часть SPARC, IBM 360/370) и форматы файлов (JPEG, PNG, FLV и др.). Сравнение многобайтовых чисел как строк при big-endian совпадает с числовым сравнением — это удобно для сортировки.
Рис. 5 — Расположение байтов в big-endian
Переключаемый порядок (bi-endian)
Некоторые архитектуры (ARM, PowerPC, MIPS, IA-64, DEC Alpha) могут работать и в little-endian, и в big-endian. Порядок задаётся при загрузке ОС или перемычками/настройками и влияет на то, как процессор интерпретирует многобайтовые данные в памяти. Такой режим называют bi-endian.
Смешанный порядок (middle-endian)
Middle-endian (смешанный порядок) встречается реже: внутри машинного слова байты могут идти в одном порядке, а сами слова в многобайтовом значении — в другом. Классический пример — хранение 64-битных чисел на части 32-битных VAX или ARM: слова в обратном порядке относительно привычного. В повседневной разработке под x86 и в сетевом коде чаще имеют дело только с little- и big-endian.
Рис. 6 — Типичное применение little- и big-endian
Пример: число в памяти
Пусть 32-битное число в шестнадцатеричном виде равно 0x0A0B0C0D. Старший байт — 0x0A, младший — 0x0D.
- Little-endian: по адресу 0x00 лежит 0x0D (LSB), затем 0x0C, 0x0B, по 0x03 — 0x0A (MSB). При чтении побайтово «слева направо» по возрастанию адреса видим: 0x0D, 0x0C, 0x0B, 0x0A.
- Big-endian: по 0x00 лежит 0x0A (MSB), затем 0x0B, 0x0C, по 0x03 — 0x0D (LSB). По возрастанию адреса: 0x0A, 0x0B, 0x0C, 0x0D.
Один и тот же набор из четырёх байтов в разном порядке даёт разное числовое значение при интерпретации как 32-битного целого. Поэтому при переносе данных между системами или между хостом и сетью порядок байтов явно задают или преобразуют.
Рис. 7 — Одно число 0x0A0B0C0D: little-endian и big-endian
В программировании
При работе с сетью и бинарными форматами порядок байтов нужно учитывать явно:
- Сеть: многобайтовые поля в заголовках (порты, длина, номера) обычно передаются в big-endian (network byte order). На хосте x86 числа хранятся в little-endian — перед отправкой их переводят в сетевой порядок, при приёме — обратно.
- Функции преобразования: в C под Unix —
htonl,htons(host to network long/short),ntohl,ntohs(network to host). Они делают swap байтов при необходимости, чтобы код работал на любой архитектуре. - Файлы и протоколы: при чтении/записи бинарных структур (например, через
structв Python) порядок задаётся символами формата:<— little-endian,>— big-endian,!— network (big). Пример:struct.pack('>I', value)записывает 32-битное беззнаковое в big-endian.
Если данные не покидают одну платформу и не пишутся в заданный внешний формат, компилятор и ОС сами используют порядок байтов текущей архитектуры; преобразование нужно только при обмене между разными порядками.
Рис. 8 — Преобразование порядка байтов при обмене с сетью
Выводы
- Бит — минимальная единица (0 или 1); байт — 8 бит; объёмы измеряют в KB, MB, GB (часто по 1024).
- Порядок байтов (endianness) — последовательность, в которой байты многобайтового значения записаны в памяти или передаются. Little-endian — младший байт по младшему адресу (типично x86). Big-endian — старший по младшему адресу (сеть, многие форматы файлов).
- Названия big-endian и little-endian связаны с аллегорией из «Гулливера» и статьёй Дэнни Коэна о порядке байтов в сообщениях.
- Для совместимости при сетевом обмене используют network byte order (обычно big-endian) и функции вроде
htonl/ntohl; при работе с бинарными файлами порядок задают в формате (например, вstruct). - Один и тот же набор байтов в разном порядке даёт разное числовое значение — при переносе данных между системами или в сеть порядок нужно явно задавать или преобразовывать.
Категории