Меня всегда смущает порядок байтов. Порядок следования байтов относится к машинному расположению байтов в числе, но в моем воображении я представляю байты, записанные как последовательности битов, и меня отвлекает порядок битов, или я подумайте о байтах в массивах, которые всегда располагаются одинаково, независимо от порядка следования байтов. Я надеюсь, что подробное описание порядка битов и байтов поможет мне лучше представить, когда я думаю о порядке следования байтов.
Биты
В английском (и многих других языках) мы пишем числа в позиционной нотации так, чтобы младшая значащая цифра была справа. Например, текущий год пишется 2019 вместо 9102. Это распространяется и на другие базы, включая бинарные.
Наши языки программирования отражают это соглашение с помощью своих побитовых операторов: сдвиг битов вправо снижает их значимость, а сдвиг влево — вверх. Можно предположить, что (2 >> 1) == 1
. В другой системе, где младший бит находится слева, сдвиг вправо будет иметь противоположный эффект, например. (2 >> 1) == 4
.
Таким образом, когда я думаю о числе как о последовательности битов, сколько бы их ни было, я представляю его как написанное, со старшим битом слева и наименее значащим битом справа.
Отдельно от написанного порядка битов стоит нумерация битов. Мы можем выбрать нумерацию цифр от наиболее значимого к наименее значимому (слева направо в письменном английском языке) или наоборот.
Наши компьютеры не адресуют биты, так что вряд ли имеет значение, что мы выбираем. Мы можем выбрать то, что наиболее удобно. В каждом разговоре, который я могу вспомнить, я нумеровал биты от младшего к старшему (справа налево). Это имеет то преимущество, что биты с одинаковыми значениями в разной ширине представления (например, 32-битные против 64-битной) имеют одинаковые нумерованные позиции. Эта схема называется LSB 0. Противоположная схема называется MSB 0.
Байты
Теперь давайте подумаем о двоичном представлении чисел, разбитых на 8-битные байты. Как нам пронумеровать эти байты? Как и в случае с битами, у нас есть два варианта: от наиболее значимого к наименее значимому (слева направо в письменном английском языке) или наоборот. Схема, в которой мы нумеруем их, начиная со старшего байта, то есть с «большого» конца, называется big-endian. Противоположная схема — с прямым порядком байтов.
Почему это важно? Нумерация битов никак не влияла на наше программное обеспечение, позволяя нам выбирать что угодно, но нумерация байтов определяет их порядок в памяти, т. е. их адреса. Последовательность байтов — это универсальный язык; это то, как мы читаем и записываем данные. Endianness определяет, как мы интерпретируем последовательность байтов как одно число.
Единственный раз, когда нам нужно беспокоиться о порядке следования байтов, — это преобразование между различными форматами сериализации. Вот два ярких примера:
- Архитектура набора инструкций. Мы можем думать о каждой инструкции как о сериализации кода этой инструкции и ее аргументов, которые могут включать числа. Большинство настольных компьютеров и ноутбуков используют процессоры с архитектурой x86 или x86–64, обе из которых имеют обратный порядок байтов. ЦП будет записывать числа в память в соответствии с порядком байтов.
- Протоколы проводной связи. Наиболее распространенные сетевые протоколы (например, TCP и UDP) имеют порядок байтов с обратным порядком. При подготовке сообщения для этих протоколов мы должны позаботиться о преобразовании между порядком байтов ЦП и порядком байтов протокола (но только для чисел, интерпретируемых протоколом, например, номера порта в заголовке TCP).
Первоначально опубликовано на сайте thejohnfreeman.com 9 апреля 2019 г.