Перейти к основному содержимому

Порядок байтов — endianness

Инженеру

Endianness (порядок байтов) — правило, в каком порядке байты многобайтового числа записываются в память. Для одного и того же значения 0x00000006 (число 6 в 32‑битном слове) байты могут идти «от старшего» или «от младшего» — и это не видно при работе на одной машине, но ломает обмен бинарными данными между x86 и некоторыми сетевыми протоколами.

Термины big-endian и little-endian ввёл Danny Cohen (1980), отсылая к спору из «Путешествий Гулливера» Свифта — с какого конца разбивать яйцо. Классический пример проблемы — обмен структурой «строка + два int» между машинами с разным порядком байт.


Байт, слово, адрес

ТерминСмысл
Байт8 бит; минимальная адресуемая ячейка в большинстве современных CPU
СловоНесколько байт, с которыми работает команда (32 или 64 бита)
АдресНомер ячейки памяти; у слова один базовый адрес, внутри — несколько байт

32‑битное слово по адресу 0 занимает байты 0…3, 64‑битное — 0…7. Вопрос endianness — какой байт считается «первым» внутри слова.


Big-endian и little-endian

РежимПорядок байтов в словеТипичные платформы
Big-endianСтарший байт по младшему адресу (слева направо в диаграммах)Старые SPARC, часть мэйнфреймов IBM, сетевые протоколы
Little-endianМладший байт по младшему адресуx86/x86-64, большинство ARM в режиме по умолчанию

Пример: 32‑битное число 6 (…00000110 в младших битах).

Адрес байта0123
Little-endian (Intel)06000000
Big-endian (SPARC)00000006

Число одно и то же для CPU своей архитектуры. Проблема начинается при копировании сырых байт на другую машину или при чтении файла, записанного на другой endianness.


Смешанные записи — строка и числа

Запись «Jim Smith, 21 год, отдел 260» в памяти часто выглядит так: строка (байты символов + нулевой терминатор до границы слова) + два int (возраст, номер отдела).

При передаче побайтно по сети без преобразования:

  • Строка может отображаться зеркально (MIJ…), если порядок байт внутри слова «перепутался» относительно ожиданий;
  • Целые числа умножаются на степени 256 — возраст 21 превращается в гигантское значение.

Универсального «просто перевернуть слово» нет: для строки нужен порядок символов, для int — иногда инверсия байт внутри слова. Поэтому в протоколах задают явный формат (JSON, Protobuf, TLV) или фиксированный network byte order.


Network byte order

В IP и многих бинарных протоколах multi-byte поля передают в big-endian (старший байт первым). В C для этого есть функции htons, htonl, ntohs, ntohl — host to network / network to host.

СитуацияПрактика
API по HTTP/JSONEndianness не важен — текст и числа в десятичном виде
Сокеты, бинарные заголовкиЯвное преобразование или стандарт big-endian
Файлы struct через fwriteНе переносимы между архитектурами без соглашения
WASM, Java .classФиксированный порядок байт в формате файла

Подробнее про переносимость бинарных структур в C — в языке C.


Как проверить на своей машине

#include <stdio.h>

int main(void) {
unsigned int x = 0x04030201;
unsigned char *p = (unsigned char *)&x;
if (p[0] == 0x01)
puts("little-endian");
else if (p[0] == 0x04)
puts("big-endian");
return 0;
}

На типичном ПК с Windows или Linux на x86-64 вывод будет little-endian.


Связь с архитектурой

Endianness — свойство ISA и реализации, а не «Windows vs Linux». Linux на ARM может быть little-endian; некоторые встраиваемые ядра — big-endian. При сравнении x86, ARM и RISC-V endianness входит в чек-лист переноса прошивки и протоколов.

Практическое правило
Текстовые форматы и JSON решают 99% задач без думания об endianness. Бинарные форматы и общая память между устройствами — всегда явная спецификация порядка байт.


Куда читать дальше

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").