Старший байт младший байт

Старший байт младший байт

Инструменты пользователя

Инструменты сайта

Содержание

Операнды поразрядных операций могут быть любого целого типа. К побитовым, или поразрядным операциям относятся:

Кроме того, рассматриваются операции сдвигов «, ».

Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов является старшим, а какой младшим. Прямая запись ячеек памяти приводит к возможным проблемам при переносе приложения с платформы на платформу. Варианты записи: от старшего к младшему или (англ. big-endian, дословно: «тупоконечный»): этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). От младшего к старшему или (англ. little-endian, дословно: «остроконечный»): запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с x86-процессорами, в связи с чем иногда его называют интеловский порядок байтов.

Чтобы получить значение младщего слова (OWORD)

Считать старшим битом самую левую единицу — ошибочно, в противном случае в системе со знаком все числа будут или нулем, или отрицательными числами.

Мы знаем, что считать можно до бесконечности, а потому при записи числа на листочке количество знаков может быть неограниченным. Понятие "старший" возникает только тогда, когда есть некоторое ограничение на количество записываемых символов (разрядов). Поэтому старший бит — это самый левый бит в записи N-битного числа, содержащей N разрядов (которые при необходимости слева добираются нулями). Просто глядя на число нельзя сказать, какой бит у него старший, нужно ещё знать, во сколько разрядов мы его хотим записать. Т.е. если мы число 128 записываем в переменную типа unsigned char (8 бит), то cтаршим битом будет единица, а если записываем в unsigned int (16 или 32 бита в зависимости от платформы), то старшим битом будет 0.

В случае знакового представления самый старший бит является знаковым (при условии что мы используем запись в дополнительном коде). И именно этот знаковый бит называют старшим (потому что больше нечего назвать этим термином). Вообще, старший бит — это крайний бит некоего абстрактного регистра (ограниченной длины) для хранения числа.

потому что только нулевой и четвертый разряды обоих операндов содержат 1.

потому что все разряды (кроме шестого) в одном из двух операндов имеют значение 1.

Заметим, что, поскольку нулевой разряд в обоих операндах имеет значение 1, нулевой разряд результата имеет значение 0.

Описанные выше операции часто используются для установки некоторых битов, причем другие биты остаются неизменными. Они удобны для фильтрации или маскирования битов.

Таким образом, х«2 сдвигает х влево на 2 позиции, заполняя освобождающиеся позиции нулями (эквивалентно умножению на 4).

Для значений без знака имеем

Эти две операции выполняют сдвиг, а также эффективное умножение и деление на степени числа 2.

Комментарии к коду.

Для понимания побитовых операторов необходимо свободно уметь работать с двоичным представлением чисел. Если это не так, остается только надеяться, что данные операторы не часто вам будут попадаться в вашей практике. Ниже следует перечень побитовых операторов с примерами их применения (примеры и результаты даны, так же, и в бинарной (двоичной) форме):

Таблица. Побитовые операторы.

Принцип работы побитовых операторов достаточно прост: JavaScript рассматривает последовательно каждый бит операндов, выполняет над ними одну из логических операций (исходя из того, что 1 — true, a 0 — false) и формирует бит результата. Исключением являются лишь операции побитового сдвига. Рассмотрим небольшой пример применения побитовых операций — определение четности числа. Если число является четным, то его первый (крайний правый) бит равен "0" и операция "&" с числом "1" вернет значение "0". Исходя из этого, напишем скрипт:

Листинг: определение четности числа

Если в результате получится значение false, то заданное число является нечетным, в противном случае, число является четным.

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

В общем случае, для представления числа M, большего 255 (здесь 255 = 2 8 − 1 <displaystyle 255=2^<8>-1> — максимальное целое число, записываемое одним байтом), приходится использовать несколько байтов. При этом число M записывается в позиционной системе счисления по основанию 256:

M = ∑ i = 0 n A i ⋅ 256 i = A 0 ⋅ 256 0 + A 1 ⋅ 256 1 + A 2 ⋅ 256 2 + ⋯ + A n ⋅ 256 n . <displaystyle M=sum _^A_cdot 256^=A_<0>cdot 256^<0>+A_<1>cdot 256^<1>+A_<2>cdot 256^<2>+dots +A_cdot 256^.>

Набор целых чисел A 0 , … , A n <displaystyle A_<0>,dots ,A_> , каждое из которых лежит в интервале от 0 до 255, является последовательностью байтов, составляющих M. При этом A 0 <displaystyle A_<0>> называется младшим байтом, а A n <displaystyle A_> старшим байтом числа M.

Поскольку компьютер не адресует отдельных битов (их можно получать только через битовые поля), порядок битов в байте важен только при физической организации хранения и передачи данных, может отличаться от устройства к устройству и прикладному программисту обычно не нужен.

Содержание

Варианты записи [ править | править код ]

Порядок от старшего к младшему [ править | править код ]

Порядок от старшего к младшему (англ. big-endian — большим концом): A n , … , A 0 <displaystyle A_,dots ,A_<0>> . Этот порядок соответствует привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 123. В этом же порядке принято записывать байты в технической и учебной литературе, если другой порядок явно не обозначен.

Этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому порядок байтов от старшего к младшему часто называют «сетевым порядком байтов» (англ. network byte order ). Этот порядок байтов используется процессорами IBM 360/370/390, SPARC, Motorola 68000 (отсюда третье название — порядок байтов Motorola, англ. Motorola byte order ).

При таком порядке байтов удобно проводить сравнение строк (можно сравнивать их целочисленными большей разрядности, каждое из которых содержит несколько символов сразу).

Порядок байтов от старшего к младшему применяется также во многих форматах файлов — например, PNG, FLV, EBML, JPEG.

Порядок от младшего к старшему [ править | править код ]

Порядок от младшего к старшему (англ. little-endian — малым концом): A 0 , … , A n <displaystyle A_<0>,dots ,A_>

Это обратный порядок по отношению к привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 321.

Этот порядок записи принят в памяти персональных компьютеров с процессорами архитектуры x86, в связи с чем иногда его называют интеловский порядок байтов (по названию компании-создателя архитектуры x86). Современные процессоры x86 позволяют работать с одно-, двух-, четырёх- и восьмибайтовыми операндами. При таком порядке байтов очень удобно то обстоятельство, что при увеличении размера (количества байт) операнда, значение его первого байта остаётся прежним: 3210 → 3210’0000. При порядке от старшего к младшему значение изменилось бы, например: 0123 → 0000’0123;

Читайте также:  Заказное письмо как доставляется

Кроме x86, такой порядок байтов применяется в архитектурах VAX (отсюда ещё одно название англ. VAX byte order [1] ), DEC Alpha и многих других.

Также порядок от младшего к старшему применяется в USB, PCI, таблице разделов GUID, он рекомендован FidoNet. Но в целом соглашение little-endian поддерживают меньше кросс-платформенных протоколов и форматов данных, чем big-endian.

Переключаемый порядок [ править | править код ]

Многие процессоры могут работать и в порядке от младшего к старшему, и в обратном, например, ARM (по умолчанию — little endian), PowerPC (но не PowerPC 970), DEC Alpha, MIPS, PA-RISC и IA-64. Обычно порядок байтов выбирается программно во время инициализации операционной системы, но может быть выбран и аппаратно перемычками на материнской плате. В этом случае правильнее говорить о порядке байтов операционной системы. Переключаемый порядок байтов иногда называют англ. bi-endian .

Смешанный порядок [ править | править код ]

Смешанный порядок байтов (англ. middle-endian) иногда используется при работе с числами, длина которых превышает машинное слово. Число представляется последовательностью машинных слов, которые записываются в формате, естественном для данной архитектуры, но сами слова следуют в обратном порядке.

В процессорах VAX и ARM используется смешанное представление для длинных вещественных чисел.

Пример [ править | править код ]

Далее приведён пример, в котором описывается размещение 4-байтового числа в ОЗУ ЭВМ, доступ к которому может производиться и как к 32-разрядному слову, и побайтно.

Все числа записаны в 16-ричной системе счисления.

Число: 0xA1B2C3D4

Представление A 1 ∗ 1000000 16 + B 2 ∗ 10000 16 + C 3 ∗ 100 16 + D 4 ∗ 1 16 = D 4 C 3 B 2 A 1 <displaystyle A1*1000000_<16>+B2*10000_<16>+C3*100_<16>+D4*1_<16>=D4C3B2A1> 161 ∗ 16 10 6 + 178 ∗ 16 10 4 + 195 ∗ 16 10 2 + 212 10 = 2712847316 10 <displaystyle 161*16_<10>^<6>+178*16_<10>^<4>+195*16_<10>^<2>+212_<10>=2712847316_<10>>
Порядок от младшего к старшему (little-endian) D 4 16 , C 3 16 , B 2 16 , A 1 16 <displaystyle D4_<16>,C3_<16>,B2_<16>,A1_<16>> 212 10 , 195 10 , 178 10 , 161 10 <displaystyle 212_<10>,195_<10>,178_<10>,161_<10>>
Порядок от старшего к младшему (big-endian) A 1 16 , B 2 16 , C 3 16 , D 4 16 <displaystyle A1_<16>,B2_<16>,C3_<16>,D4_<16>> 161 10 , 178 10 , 195 10 , 212 10 <displaystyle 161_<10>,178_<10>,195_<10>,212_<10>>
Порядок, принятый в PDP-11 (PDP-endian) B 2 16 , A 1 16 , D 4 16 , C 3 16 <displaystyle B2_<16>,A1_<16>,D4_<16>,C3_<16>> 178 10 , 161 10 , 212 10 , 195 10 <displaystyle 178_<10>,161_<10>,212_<10>,195_<10>>

Определение порядка байтов [ править | править код ]

Порядок байтов в конкретной машине можно определить с помощью программы на языке Си (testbyteorder.c):

Результаты запуска на big-endian машине (SPARC):

Результаты запуска на little-endian машине (x86):

Вещественные числа [ править | править код ]

Хранение вещественных чисел может зависеть от порядка байт; так, на x86 используются форматы IEEE 754 со знаком и порядком числа в старших байтах.

Юникод [ править | править код ]

Если Юникод записан в виде UTF-16 или UTF-32, то порядок байтов является существенным. Одним из способов обозначения порядка байтов в юникодовых текстах является постановка в начале специального символа BOM (byte order mark, маркер последовательности байтов, U+FEFF) — «перевёрнутый» вариант этого символа (U+FFFE) не существует и не допускается в текстах.

Символ U+FEFF изображается в UTF-16 последовательностью байтов 0xFE 0xFF (big-endian) или 0xFF 0xFE (little-endian), а в UTF-32 — последовательностью 0x00 0x00 0xFE 0xFF (big-endian) или 0xFF 0xFE 0x00 0x00 (little-endian).

Проблемы совместимости и конвертация [ править | править код ]

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

Для преобразования между сетевым порядком байтов (англ. network byte order ), который всегда big-endian, и порядком байтов, использующимся на машине (англ. host byte order ), стандарт POSIX предусматривает функции htonl() , htons() , ntohl() , ntohs() :

  • uint32_t htonl(uint32_t hostlong); — конвертирует 32-битную беззнаковую величину из локального порядка байтов в сетевой;
  • uint16_t htons(uint16_t hostshort); — конвертирует 16-битную беззнаковую величину из локального порядка байтов в сетевой;
  • uint32_t ntohl(uint32_t netlong); — конвертирует 32-битную беззнаковую величину из сетевого порядка байтов в локальный;
  • uint16_t ntohs(uint16_t netshort); — конвертирует 16-битную беззнаковую величину из сетевого порядка байтов в локальный.

В случае совпадения текущего порядка байтов и сетевого функции могут быть «пустыми» (то есть, не менять порядка байтов). Стандарт также допускает, чтобы эти функции были реализованы макросами.

Существует много языков и библиотек со средствами конвертации в оба основных порядка байт и обратно.

Ядро Linux: le16_to_cpu(), cpu_to_be32(), cpu_to_le16p(), и так далее;

Ядро FreeBSD: htobe16(), le32toh(), и так далее;

Овладейте навыками создания кода, не зависящего от порядка байтов

Для усвоения концепции порядка байтов (см. endianness), не обязательно разбираться в логических схемах организации памяти — нужно только понимать, что память представляет собой один большой массив. Массив содержит байты. Программисты используют адрес для указания на местоположение требуемого массива в памяти.

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

Этот термин означает, как хранит и использует байты система: порядок от старшего к младшему (запись начинается со старшего байта и заканчивается младшим, big endian), порядок от младшего к старшему (запись информации начинается с младшего и заканчивается старшим, little endian).

Каждый адрес указывает на один элемент массива. Каждый элемент является обычно одним байтом. В некоторых конфигурациях памяти адрес хранит другую информацию кроме байта, однако такая реализация сейчас встречается достаточно редко, поэтому будем считать, что все адреса памяти хранят только байты.

Хранение байтов в памяти

Мы будем оперировать 32-мя битами, т.е. четырьмя байтами. Целые числа или числа с плавающей точкой с обычной точностью записываются в 32 битах. Но поскольку каждый адрес в памяти может хранить только один байт, а не четыре, то 32-х битное число надо разбить на 4 байта. Например, предположим, что есть 32-х битное число, записанное как 12345678, которое является шестнадцатеричным. Поскольку каждая шестнадцатеричная цифра представляется четырьмя байтами, то необходимо восемь шестнадцатеричных чисел для представления рассматриваемого 32-х битного значения. Четыре байта это: 12, 34, 56, и 78. Есть два способа хранить это в памяти, как показано ниже.

    От старшего к младшему: cтарший байт хранится в младшем адресе памяти, как показано ниже:

Таблица 1. Хранение байтов от старшего к младшему (Big-endian)

Адрес Значение
1000 12
1001 34
1002 56
1003 78

От младшего к старшему: ссылка на младший байт в младшем адресе памяти, как показано ниже:

Таблица 2. Хранение байтов от младшего к старшему (little-endian)

Адрес Значение
1000 78
1001 56
1002 34
1003 12

Обратите внимание на предыдущую таблицу — числа находятся в обратном порядке. Для запоминания порядков полезно следующее правило: младший байт записывается первым (порядок "от младшего к старшему" — little-endian), старший байт записывается первым (порядок "от старшего к младшему" — big-endian).

Читайте также:  Не запускается obs studio

Регистры и порядок байтов

Порядок байтов имеет значения только тогда, когда нужно разбить многобайтовую последовательность и записать полученные байты в последовательные участки памяти. Однако если имеется 32-х битный регистр, хранящий 32-х битное значение, то нет смысла говорить о порядке размещения байтов в памяти. Регистр не чувствителен к порядку "от старшего к младшему" или "от младшего к старшему"; регистр только хранит 32-х битное значение. Крайне правый бит является младшим, крайне левый бит является старшим.

Некоторые люди считают, что регистр имеет порядок "от старшего к младшему", потому что он записывает старшие байты в младшие адреса памяти.

Важность порядка байтов

Порядок байтов является атрибутом системы, который определяет, представляются ли целые числа слева-направо или справа-налево. В сегодняшнем мире виртуальных машин и гигагерцевых процессоров многие программисты задумываются, почему они должны учитывать вопрос, рассматриваемый в этой статье? К сожалению, необходимо учитывать порядок байтов каждый раз при разработке аппаратного или программного обеспечения. И, в общем-то, нет универсального правила о том, какой порядок байтов использовать.

Все процессоры должны быть разработаны с учетом либо порядка "от младшего к старшему" или "от старшего к младшему". Например, процессоры Intel® семейства 80×86 и их клоны используют "от младшего к старшему", в то время как процессоры Sun SPARC, Motorola 68K, и PowerPC® используют порядок "от старшего к младшему".

Почему порядок байт так важен? Представьте, что нужно записывать целочисленные значения в файл, и послать этот файл компьютеру, который использует противоположный порядок чтения байтов; этот компьютер прочтет записанное вам в файл значение неверно. Это происходит из-за разных порядков размещения байтов в памяти; в этом случае надо читать значение задом наперед для его корректности.

Порядок записи байт в память представляет собой большую проблему при пересылке через сеть. Еще раз повторю, что если послать число, созданное в одном порядке записи байтов, на компьютер, использующий противоположный порядок записи, то возникнет проблема. Ситуация усложняется еще больше, если неизвестен порядок записи байтов на удаленной машине.

Пример 1 показывает, к чему приводит программирование без учета различий в направлении записи байтов.

Пример 1. Программирование без учета различий в направлении записи байтов

Приведенный выше код корректно скомпилируется на любом компьютере. Однако выводимый результат будет разным из-за различных порядков записи байтов в память. Вывод программы после просмотра его утилитой hexdump , будет таким, как в примерах 2 и 3.

Пример 2. Вывод команды hexdump -C на компьютере с порядком "от старшего к меньшему"
Пример 3. Вывод команды hexdump -C с порядком записи "от младшего к старшему"

Влияние порядка хранения байт в памяти на программный код

Различие в порядке байтов далеко не всегда влияет на результат операций. Если выполняются побитовые операции или операции побитового сдвига на целочисленных значениях, то не надо учитывать порядок байтов в памяти. Компьютер упорядочивает многочисленные байты таким образом, что младший байт всегда остается самым младшим, старший байт всегда является старшим.

Естественно в таком случае задаться вопросом, могут ли строки сохраняться в каком-либо необычном порядке, характером для конкретного компьютера. Для ответа на этот вопрос, вернемся к основам организации массивов. Строка в языке C представляет собой массив символов. Каждый символ требует одного байта памяти, при условии, что символы отображаются в кодировке ASCII. В массиве адрес последовательных элементов возрастает. Таким образом, адрес &arr[i] меньше чем адрес &arr[i+1]. Хотя это и не является очевидным, если что-либо хранится в ячейках памяти, адреса которых последовательно увеличиваются, оно будет записано в файл в такой же возрастающей последовательности. При записи в файл обычно задается адрес в памяти и число байтов, которое нужно записать в файл, начиная с этого адреса.

Предположим, есть строка man . Будем считать, что m хранится по адресу 1000, a по адресу 1001, и n по адресу 1002. Символ конца строки хранится по адресу 1003. Следуя из того, что строки в С являются массивами символов, к ним применяются правила работы с символами. В отличие от типов int или long, можно легко различать отдельные байты в строке. Индексация массивов используется для обеспечения доступа к байтам (символам) строки, нельзя просто обращаться к отдельным байтам типов int или long — для этого надо использовать указатели. Отдельные байты в int или long в большей или меньшей степени скрыты от программиста.

Теперь представим, что эту строку нужно записывать в файл при помощи метода типа write() . Ставим указатель на m и задаем число байтов, которое нужно записать в файл (в данном случае четыре). Метод write() обрабатывает байт за байтом и записывает их в файл начиная с m и заканчивая символом конца строки.

Итак, мы доказали, что порядок байтов не влияет на представление строк в языке С.

Порядок байтов имеет значение, когда вы используете приведение типов, которое зависит от конкретного порядка байтов. Пример такой ситуации показан в примере 4, но учтите, что существует много различных приведений типов, которые могут вызвать проблемы.

Пример 4. Принудительное задание порядка байтов

Каким будет значение x ? Давайте взглянем, что делает этот код. Мы создали двухбайтный массив, а затем преобразовали его к типу short. Используя массив, мы фактически принуждаем систему к использованию какого-либо конкретного порядка байтов; давайте посмотрим, как система обработает эти два байта.

В случае, если используется подход "от младшего к старшему", 0 и 1 интерпретируются задом наперед и будут представлены как 0,1. Так как старший байт 0, а младший байт 1, значение x будет равным 1.

С другой стороны, в системе с порядком "от старшего к младшему" старшим байтом будет 1 и значение переменной x будет равным 256.

Определения порядка байтов во время выполнения программы

Один из способов определить порядок байтов в системе — это проверить расположение в памяти предопределенной константы. Напомним, что размещение единицы (1) типа целочисленного 32-х битного числа будет следующим — 00 00 00 01 для порядка "от старшего к младшему" и 01 00 00 00 для порядка "от младшего к старшему". Взглянув на первый байт этой константы, можно указать порядок байтов у конкретной платформы, и затем предпринять наиболее эффективное в данной ситуации действие.

Пример 5 проверяет первый байт целого числа i для того, чтобы определить, является оно 0 или 1. Если оно равно 1, текущая платформа использует режим байтов в памяти "от младшего к старшему", а если 0 — то режим "от старшего к младшему".

Пример 5. Определение порядка байтов

Другой способ определить порядок байтов состоит в использовании символьных указателей на байты в числе типа int и затем проверить первый байт — является он 0 или 1. Пример 6 иллюстрирует этот способ.

Читайте также:  Потолочная лампа xiaomi yeelight
Пример 6. Символьные указатели

Сетевой порядок байтов

Сетевые стеки и протоколы также должны определять свою последовательность байтов, иначе два узла сети с разным порядком байтов просто не смогут взаимодействовать. Это наиболее яркий пример влияния порядка байтов на программы. Все уровни протокола TCP/IP работают в режиме "от старшего к младшему". Любое 16-ти или 32-х битное значение внутри заголовков различных уровней (такое как IP-адрес, длина пакета, контрольная сумма) должны отсылаться и получаться так, чтобы старший байт был первым.

Порядок байтов "от старшего к младшему", используемый в протоколе TCP/IP, иногда еще называют сетевым порядком байтов. Даже если компьютеры в сети используют порядок "от младшего к старшему", многобайтные целочисленные значения для передачи их по сети должны быть преобразованы в сетевой порядок байтов, а затем еще раз преобразованы назад в порядок "от младшего к старшему" на принимающем компьютере.

Предположим, что нужно установить TCP-соединение с компьютером, чей IP-адрес равен 192.0.1.2. IPv4 использует уникальное 32-х битное целое число для идентификации каждого компьютера в сети. Разделенный точками IP-адрес должен быть представлен в качестве целочисленного значения.

Например, ПК на базе 80×86 связывается с сервером на базе SPARC через Интернет. Без каких-либо дополнительных действий со стороны пользователя процессор 80×86 может преобразовать 192.0.1.2 в целочисленное число с последовательностью байтов "от младшего к старшему", равное 0x020100C0, и передать байты в последовательности 02 01 00 C0. SPARC получит байты в порядке 02 01 00 C0, переведет байты в порядок "от старшего к младшему" 0x020100c0, и неправильно прочтет IP-адрес 2.1.0.192.

Если стек работает на процессоре, использующем порядок байтов "от младшего к старшему", он должен переупорядочить во время выполнения байты каждого многобайтного значения из заголовков уровней протокола TCP/IP. Если стек работает в режиме байтов "от большего к меньшему", то нет повода для беспокойств. Чтобы стек обладал переносимостью (работал на процессоре обоих типов), он должен уметь принимать решение о необходимости совершения переупорядочивания байтов во время компиляции.

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

htons() Переупорядочивает байты 16-ти битового беззнакового значения из порядка, используемого в текущем процессоре, в сетевой порядок байтов. Название макроса можно расшифровать как "host to network short" ("порядок в беззнаковом коротком числе преобразовать в сетевой порядок байтов"). htonl() Переупорядочивает байты 32-х битного беззнакового значения из порядка, используемого в текущем процессоре, в сетевой порядок байтов. Название макроса можно расшифровать как "host to network long" ("порядок в беззнаковом длинном числе преобразовать в сетевой порядок байтов"). ntohs() Переупорядочивает байты 16-ти битного беззнакового значения из сетевого порядка байтов в порядок байтов, используемый на текущем процессоре. Название макроса можно расшифровать как "network to host short" ("из сетевого порядка в порядок для используемого процессора, 16-ти битное число"). ntohl() Переупорядочивает байты 32-х байтного беззнакового значения из сетевого порядка в порядок байтов, используемый на текущем процессоре. Название макроса может быть расшифровано как "network to host long" ("из сетевого порядка в порядок для используемого процессора, 32-ти битное число").

Рассмотрим программу из примера 7.

Пример 7. Программа на языке С

Эта программа показывает, как хранится переменная x типа long, хранящее значение 112A380 (шестнадцатеричное).

Когда эта программа выполняется на процессоре, использующем порядок байтов "от младшего к старшему", она выводит информацию как в примере 8.

Пример 8. Результат работы программы на процессоре с режимом "от младшего к старшему"

Если посмотреть на отдельные байты x, то видно, что младший байт (0x80) находится по меньшему адресу. После этого вызвать htonl( ) для конвертирования в сетевой порядок байтов, то в результате старший байт (0x1) окажется по меньшему адресу. Естественно, что если распечатать значение переменной x после изменения ее порядка байтов, то получится бессмысленное число.

Пример 9 показывает результаты работы той же программы на процессоре с режимом "от старшего к младшему".

Пример 9. Результат работы программы на процессоре с режимом "от старшего к младшему"

Здесь видно, что самый старший байт (0x1) записан под меньшим адресом. Вызов htonl() для конвертирования в сетевой порядок не изменит ничего потому, что порядок байтов "от старшего к младшему".

Изменение на обратный порядка байтов

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

Создадим набор функций, которые автоматически меняет на обратный порядок байтов заданного параметра в зависимости от порядка байтов на компьютере.

Сначала нужно разобраться с параметром s типа short , разделив его два байта, а затем "склеить" их в обратном порядке. Как показано в примере 10 ниже, функция вернет реверсированное значение переменной типа short в случае, если процессор использует порядок байтов "от младшего к старшему". В противном случае функция оставит прежним значение переменной s .

Пример 10. Метод 1: Использование побитового сдвига и склеивания битов

В функции ниже преобразуется переменнаяю типа short , чтобы представить ее как массив символов, а затем создается новый массив, являющийся обратным первому в случае, если процессор использует режим "от младшего к старшему".

Пример 11. Метод 2: Использование указателей на символьный массив

Теперь перейдем к типу int .

Пример 12. Метод 1: Использование побитового сдвига и склеивания байтов для типа int

Это в большей или меньшей степени соответствует тому, что мы раньше делали для изменения на обратный порядка для типа short , но для четырех байтов, а не двух.

Пример 13. Метод 2: Использование указателей на символьный массив для типа int

То же самое мы делали для реверсирования переменной типа short , но здесь обрабатывались четыре байта.

Точно также можно менять на обратный порядок байтов для типов float, long, double и других типов, но рассмотрение этих вопросов выходит за рамки данной статьи.

Заключение

По большому счету, нет особого преимущества в использовании того или иного порядка байтов. Оба порядка распространены и используются в архитектуре многих ЭВМ. Процессоры, работающие в режиме "от младшего к старшему" используются на большинстве персональных компьютеров.

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

Ссылка на основную публикацию
Сравнить технические характеристики rx330 и rx350
Линейка популярных люксовых SUV Lexus RX пополнилась новой модификацией – RX 350. Теперь покупателем RX быть еще приятнее – ведь...
Сколько рублей получают ютуберы
Видеохостинг YouTube — не только развлекательная площадка, но и хороший источник дохода. Тысячи пользователей выкладывают ролики, пытаясь привлечь внимание аудитории....
Сколько света мотает компьютер
Выбирая комплектующие для персонального компьютера (ПК) обычно обращают внимание на производительность и объем памяти, порой забывая о том, сколько же...
Сравнить процессоры кирин и снапдрагон
Snapdragon 636 vs. Kirin 960: кто лучше? Результаты тестов и сравнительных таблиц, описанных в этой статье, помогут определить, какой из...
Adblock detector