Что такое порядок байтов
Многобайтовое число приходится хранить по одному байту, и для этого есть два разумных порядка. Big-endian помещает старший байт по младшему адресу — так, как мы пишем числа: 0x12345678 становится 12 34 56 78. Little-endian ставит младший байт первым: 78 56 34 12. x86, x86-64 и (по умолчанию) ARM — little-endian; сетевые протоколы (IP, TCP, DNS), class-файлы Java, PNG и большинство форматов больших машин — big-endian, поэтому «сетевой порядок байтов» означает big-endian.
Когда это важно
Внутри одной программы на одной машине — никогда: об этом заботится CPU. Важно это становится в момент, когда байты пересекают границу: запись структуры в файл, чтение пакета, обмен с датчиком по SPI, разбор двоичного формата файла или интерпретация hex-дампа. Прочитать 78 56 34 12 в дампе памяти x86 и решить, что это 0x78563412, — классическая ошибка.
Функции
| Язык | Хост → сеть (big-endian) | Произвольный обмен |
|---|---|---|
| C | htonl, htons, htobe64 | __builtin_bswap32 |
| Go | binary.BigEndian.PutUint32 | bits.ReverseBytes32 |
| Python | struct.pack('>I', x) | x.to_bytes(4, 'little') |
| Rust | x.to_be_bytes() | x.swap_bytes() |
| JavaScript | DataView.setUint32(o, x) | DataView с littleEndian=true |
UTF-16 и BOM
У текста в UTF-16 та же проблема, поэтому файлы могут начинаться с метки порядка байтов: FE FF для big-endian, FF FE для little-endian. У UTF-8 порядка байтов нет, и BOM ему не нужен.
Вопросы
Какой порядок байтов использует мой компьютер?
Почти наверняка little-endian: все CPU x86 и x86-64 такие, а ARM (телефоны, Apple Silicon, Raspberry Pi) на практике работает в little-endian. Big-endian сохраняется в сетевых протоколах и некоторых встраиваемых и мейнфреймовых системах (s390x, старые PowerPC, SPARC).
Почему в сети big-endian?
Историческая договорённость времён раннего ARPANET и машин IBM/Motorola, закреплённая в RFC 1700. Все последующие протоколы ей следуют, поэтому в каждом socket API есть htons/htonl.
Влияет ли порядок байтов на биты внутри байта?
Нет. Байт всегда читается целиком. Порядок битов возникает только в последовательных протоколах и некоторых алгоритмах CRC, и это отдельный вопрос.
Как определить порядок байтов во время выполнения?
Запишите 1 в 32-битное целое и посмотрите на первый байт: 1 означает little-endian. На практике лучше использовать явные функции преобразования, чтобы код работал везде.
Что такое middle-endian?
PDP-11 хранил 32-битные значения как две little-endian 16-битные половины в порядке big-endian (34 12 78 56). Он вымер, но термин до сих пор применяют к форматам дат вроде MM-DD-YYYY.