Big-endian и little-endian: порядок следования байтов и причём тут Гулливер

#cs

В этой статье мы поговорим о понятиях big-endian и little-endian в computer science.

Эта запись также доступна в канале Telegram “DEV: Рубиновые тона”, а обсудить же эту тему можно в нашем чате Telegram.

Дом, который построил Свифт

Частенько в руководствах и документации можно встретить термины big-endian и little-endian — да хотя бы в статье про кодировки UTF8 и ASCII. Но что эти понятия вообще значат? На самом деле, всё довольно просто: это буквально война тупоконечников и остроконечников (я серьёзно).

Когда-то давно Джонатан Свифт написал роман “Путешествия Гулливера” — помните такой? Там была история, что, дескать, изначально варёные яйца лилипуты разбивали с тупого конца, но потом один из императоров умудрился себе порезать руку за завтраком, очищая яичко, после чего был издан указ: разбивать яйца только с острого конца, иначе будут применяться санкции.

Это привело к кровавым бунтам, тысячи человек пошли на казнь, так как, следуя заветам предков, всё равно разбивали яйца с тупого конца. По этой теме писались книги (хотя тупоконечную литературу запрещали), устраивались диспуты, и так далее, хотя в главном трактате некоего пророка было написано просто “разбивайте так, как вам больше нравится”. Скажем прямо, в реальной жизни подобный идиотизм тоже встречается частенько. Это, конечно, едкая сатира, но она напрямую связана с нашим вопросом.

В оригинале “тупоконечники” — это “big endians”, а их противники — “little endians”. Отсюда и пошли эти термины; впервые в далёком 80-м году их употребил Дэнни Коэн, один из участников проекта ARPANet. Это была во многом шутка, но в итоге словечки прижились.

Порядок следования байтов

Предположим, у нас есть шестнадцатеричное число 0x12345678, и оно размещается в памяти, начиная с адреса 0x100 (про организацию память можно глянуть стрим). Каждая двойка шестнадцатеричных чисел (12, 34 и так далее) занимает по 8 бит, потому что каждое число hex занимает 4 бит: 0x0 = 0b0000, 0xf = 0b1111. Следовательно, для хранения этого числа потребуется 4 байта или 32 бита (это называется “слово”, “word”). Если принять, что каждый адрес в памяти указывает на 8 бит информации, то наше число займёт адреса с 0x100 по 0x103. Но вопрос в том, как эти пары там разместить: справа налево или слева направо?

Можно сделать так:

100  101  102  103

12   34   56   78

Но можно сделать и так:

100  101  102  103

78   56   34   12

То есть сначала может идти “самая значимая” пара (это 0x12), а может, наоборот, наименее значимая (0x78). Казалось бы, выбор очевиден, но можно вспомнить хотя бы о том, что некоторые народы читают справа налево, а кто-то вообще пишет столбиком. Так что, на самом деле, всё не так однозначно™.

Поэтому подход, когда наиболее значимый байт идёт на первой позиции, называется “big endian” или BE (большинству из нас это куда привычнее), а “little endian” или LE — это когда сначала идёт наименее значимый байт. В разных машинах может задействоваться один из двух подходов, к примеру, многие устройства (но не все) от Oracle используют режим big endian. Впрочем, есть чипы вида bi-endian, которые умеют работать в обоих режимах.

Кроме того, многое зависит от самой операционной системы. Так, Android и iOS используют именно little-endian, с Windows в целом аналогичная история. В сетевых же протоколах, напротив, используется вариант big endian (принятую по сети информацию может потребоваться переставить обратно в вариант little endian, в зависимости от машины).

Есть ли принципиальная разница?

На самом деле, с технической точки зрения нет особенной разницы, какой вариант представления использовать, равно как и нет разницы, с какой стороны разбивать яйцо. Для обычных программистов знать, какой режим использует ОС, особенно не нужно, потому что это должны учитывать компиляторы.

Однако этот термин может встречаться в других местах — например, в документации Solidity и Ethereum, где рассказывается о хранении данных в слотах (к примеру, uint хранится в виде big endian, равно как и селектор функции в calldata).

Интересно, что сказал бы по этому поводу Свифт…