Что такое байты как польз
Текущая версия страницы пока не проверялась опытными участниками и может значительно отличаться от версии, проверенной 31 августа 2019;
проверки требуют 8 правок.
У этого термина существуют и другие значения, см. Byte.
Байт (англ. byte) (русское обозначение: байт и Б; международное: B, byte)[1] — единица хранения и обработки цифровой информации; совокупность битов, обрабатываемая компьютером одновременно. В современных вычислительных системах байт состоит из 8 бит и, соответственно, может принимать одно из 256 (от 0 до 255) различных значений (состояний, кодов). Однако в истории компьютерной техники существовали решения с иными размерами байта (например, 6, 32 или 36 бит), поэтому иногда в компьютерных стандартах и официальных документах для однозначного обозначения группы из 8 бит используется термин «октет» (лат. octet).
В большинстве вычислительных архитектур байт — это минимальный независимо адресуемый набор данных.
История[править | править код]
Название «байт» было впервые использовано в июне 1956 года В. Бухгольцем (англ. Werner Buchholz) при проектировании первого суперкомпьютера IBM 7030 Stretch для пучка одновременно передаваемых в устройствах ввода-вывода битов числом от одного до шести. Позже, в рамках того же проекта, байт был расширен до восьми бит. Слово byte было выбрано как намеренно искажённое слово bite, произносящееся так же (англ. bite — «кусок»; «часть чего-либо, отделённая за один укус»; ср. также появившееся позже название для 4-битной единицы «ниббл» от англ. nibble — «покусывать»). Изменённое написание byte через y вместо i потребовалось, чтобы избежать смешения со словом «бит» (bit)[2]. В печати слово byte впервые появилось в июне 1959 года[3].
Ряд ЭВМ 1950-х и 1960-х годов (БЭСМ-6, М-220) использовали 6-битные символы в 48-битных или 60-битных машинных словах. В некоторых моделях ЭВМ производства Burroughs Corporation (ныне Unisys) размер символа был равен 9 битам. В советской ЭВМ Минск-32 использовался 7-битный байт.
Байтовая адресация памяти была впервые применена в системе IBM System/360. В более ранних компьютерах адресовать можно было только целиком машинное слово, состоявшее из нескольких байтов, что затрудняло обработку текстовых данных.
8-битные байты были приняты в System/360, вероятно, из-за использования BCD-формата представления чисел: одна десятичная цифра (0—9) требует 4 бита (тетраду) для хранения; один 8-битный байт может представлять две десятичные цифры. Байты из 6 бит могут хранить только по одной десятичной цифре, два бита остаются незадействованными.
По другой версии, 8-битный размер байта связан с 8-битным же числовым представлением символов в кодировке EBCDIC.
По третьей версии, из-за двоичной системы кодирования в компьютерах наиболее выгодными для аппаратной реализации и удобными для обработки данных являются длины слов, кратные степеням двойки, в том числе и 1 байт = 23 = 8 бит. Системы и компьютеры с длинами слов, не кратными числу 2, отпали из-за невыгодности и неудобства.
Постепенно 8-битные байты стали стандартом де-факто; с начала 1970-х в большинстве компьютеров байты состоят из 8 бит, а размер машинного слова кратен 8 битам.
Количество состояний (кодов) в байте[править | править код]
Количество состояний (кодов, значений), которое может принимать 1 восьмибитный байт с позиционным кодированием, определяется в комбинаторике. Оно равно количеству размещений с повторениями и вычисляется по формуле:
возможных состояний (кодов, значений), где
Производные единицы[править | править код]
Кратные и дольные приставки для образования производных единиц для байта применяются не как обычно. Уменьшительные приставки не используются совсем, а единицы измерения информации, меньшие, чем байт, называются специальными словами — ниббл (тетрада, полубайт) и бит. Увеличительные приставки кратны либо 1024 = 210, либо 1000 = 103: 1 кибибайт равен 1024 байтам, 1 мебибайт — 1024 кибибайтам или 1024×1024 = 1 048 576 байтам и т. д. для гиби-, теби- и пебибайтов. В свою очередь 1 килобайт равен 1000 байтам, 1 мегабайт — 1000 килобайтам или 1000×1000 = 1 000 000 байтам и т. д. для гига-, тера- и петабайт. Разница между ёмкостями (объёмами), выраженными в кило = 103 = 1000 и выраженными в киби = 210 = 1024, возрастает с ростом веса приставки. МЭК рекомендует использовать двоичные приставки — кибибайт, мебибайт, йобибайт и т. п.
Иногда десятичные приставки используются и в прямом смысле, например, при указании ёмкости жёстких дисков: у них гигабайт (гибибайт) может обозначать не 1 073 741 824 = 10243 байтов, а миллион килобайтов (кибибайтов), то есть 1 024 000 000 байтов, а то и просто миллиард байтов.
Обозначение[править | править код]
Использование русской прописной буквы «Б» для обозначения байта регламентирует Межгосударственный (СНГ) стандарт ГОСТ 8.417-2002[4] («Единицы величин») в «Приложении А» и Постановление Правительства РФ от 31 октября 2009 г. № 879. Кроме того, констатируется традиция использования приставок СИ вместе с наименованием «байт» для указания множителей, являющихся степенями двойки (1 Кбайт = 1024 байт, 1 Мбайт = 1024 Кбайт, 1 Гбайт = 1024 Мбайт и т. д., причём вместо строчной «к» используется прописная «К»), и упоминается, что подобное использование приставок СИ не является корректным. По ГОСТ IEC 60027-2-2015 строчная «к» соответствует 1000 и «Ки» — 1024, так 1 КиБ = 1024 Б, 1 кБ = 1000 Б.
Использование прописной буквы «Б» для обозначения байта соответствует требованиям ГОСТ и позволяет избежать путаницы между сокращениями от байт и бит. Запись со строчной буквой в виде «Кб» (Мб, Гб) для обозначения байта будет не соответствовать международному стандарту IEC (и локализованному по нему ГОСТ). Однако авторы орфографического словаря[5] приводят строчную форму «б» (и «Кб», «Мб», «Гб») для байта, как не образованную от фамилии.
Следует учитывать, что в ГОСТ 8.417, кроме «бит», для бита нет однобуквенного обозначения, поэтому использование записи вроде «Мб» как синонима для «Мбит» не соответствует этому стандарту. Но в некоторых документах используется сокращение b для bit: IEEE 1541-2002, IEEE Std 260.1-2004, в нижнем регистре: ГОСТ Р МЭК 80000-13—2016, ГОСТ IEC 60027-2-2015.
В международном стандарте МЭК IEC 60027-2 от 2005 года[6] для применения в электротехнической и электронной областях рекомендуются обозначения:
- bit — для бита;
- o, B — для октета, байта. Причём о — единственное указанное обозначение во французском языке.[источник не указан 150 дней]
Склонение[править | править код]
Кроме обычной формы родительного падежа множественного числа (байтов, килобайтов, битов) существует счётная форма «байт»[7], которая используется в сочетании с числительными: 8 байт, 16 килобайт. Счётная форма является разговорной. Точно так же, например, с килограммами: обычная форма родительного падежа употребляется, если нет числительного, а в сочетании с числительным могут быть варианты: 16 килограммов (стилистически нейтральная обычная форма) и 16 килограмм (разговорная счётная форма).
См. также[править | править код]
- Машинное слово
- Двоичная система счисления
- Генетический код
- Трайт
Примечания[править | править код]
- ↑ Положение о единицах величин, допускаемых к применению в Российской Федерации. Утверждено Постановлением Правительства РФ от 31 октября 2009 г. № 879 (недоступная ссылка). Дата обращения 23 июля 2015. Архивировано 2 ноября 2013 года.
- ↑ Buchholz W. The Word ‘Byte’ Comes of Age… (англ.) // Byte Magazine. — 1977. — Vol. 2, iss. 2. — P. 144.
- ↑ Blaauw G. A., Brooks F. P., Buchholz W. Processing Data in Bits and Pieces (англ.) // IRE Transactions on Electronic Computers. — June 1959. — P. 121.
- ↑ ГОСТ 8.417-2002 («Единицы величин») «Приложение А» Архивная копия от 8 ноября 2015 на Wayback Machine.
- ↑ Приложение 1 Основные общепринятые графические сокращения // Русский орфографический словарь: около 200 000 слов / Российская академия наук. Институт русского языка имени В. В. Виноградова / Под. ред. В. В. Лопатина О. Е. Ивановой. — 4-е, испр. и доп. — М.: АСТ-ПРЕСС КНИГА, 2013. — С. 859—872. — 896 с. — (Фундаментальные словари русскою языка). — ISBN 978-5-462-01272-3.
- ↑ фр. NORME INTERNATIONALE CEI, Troisième édition, англ. INTERNATIONAL STANDARD IEC, Third edition — 60027-2, от 2005-08, с. 5, 112—117.
- ↑ Русский орфографический словарь: около 180 000 слов [Электронная версия] / О. Е. Иванова, В. В. Лопатин (отв. ред.), И. В. Нечаева, Л. К. Чельцова. — 2-е изд., испр. и доп. — М.: Российская академия наук. Институт русского языка имени В. В. Виноградова, 2004. — 960 с. — ISBN 5-88744-052-X.
Ссылки[править | править код]
- ГОСТ 8.417-2002 («Единицы величин») «Приложение А»
Источник
Чтобы досканально разобраться что такое Биты, что такое Байты и зачем всё это нужно, давайте сначала стоит немного остановимся на понятии «Информация», так как именно на ней построена работа вычислительной техники и сетей передачи данных, в том числе и нашего любимого Интернета.
Для человека, Информация — это некие знания или сведения, которыми обмениваются люди в процессе общения. Сначала знаниями обменивались устно, передавая друг другу, затем появилась письменность и информацию стали передавать уже с помощью рукописей, а затем уже и книг. Для вычислительных систем Информация — это данные которые собираются, обрабатываются, сохраняются и передаются дальше между звеньями системы, либо между разными компьютерными системами. Но если раньше информация помещалась в книги и её объём можно было хоть как-то наглядно оценить, например в библиотеке, то в условиях цифровых технологий она стала вирутальной и её нельзя измерить с помощью обычной и привычной метрической системы, к которой мы привыкли. Поэтому были введены единицы измерения информации — Биты и Байты.
Бит информации
В компьютере информация хранится на специальных носителях. Вот самые основные и знакомые большинству из нас:
– жесткий диск (HDD, SSD)
– оптический диск (CD, DVD)
– съёмные USB-диски (флешки, USB-HDD)
– карты памяти (SD, microSD и т.п.)
Ваш персональный компьютер или ноутбук получает информацию, в основном в виде файлов с различным объёмом данных. Каждый из этих файлов любой носитель данных на аппаратном уровне получает, обрабатывает, хранит и передаёт в виде последовательности сигналов. Есть сигнал — единица, нет сигнала — ноль. Таким образом вся храняшаяся на жестком диске информация — документы, музыка, фильмы, игры — предствалена в виде нулей: 0 и единиц: 1. Эта система исчисления называется двоичной (используется всего два числа).
Вот одна единица информации (без разницы 0 это или 1) и называеся бит. Само слово bit пришло к нам как аббревиатура от binary digit — двоичное число. Что примечательно, в английском языке есть слово bit — немного, кусочек. Таким образом, бит — это самая наименьшая единица объёма информации.
Сколько битов в Байте
Как Вы уже поняли выше, сам по себе, бит — это самая маленькая единица в системе измерения информации. Оттого и пользоваться ею совсем неудобно. В итоге, в 1956 году Владимир Бухгольц ввёл ещё одну единицу измерения — Байт, как пучок из 8 бит. Вот наглядный пример байта в двоичной системе:
00000001
10000000
11111111
Таким образом, вот эти 8 бит и есть Байт. Он представляет собой комбинацию из 8 цифр, каждая из которых может быть либо единицей, либо нулем. Всего получается 256 комбинаций. Вот как то так.
Килобайт, Мегабайт, Гигабайт
Со временем, объёмы информации росли, причём в последние годы в геометрической прогрессии. Поэтому, решено было использовать приставки метрической системы СИ: Кило, Мега, Гига, Тера и т.п.
Приставка «кило» означает 1000, приставка «мега» подразумевает миллион, «гига» — миллиард и т.д. При этом нельзя проводить аналогии между обычным килобитом и килобайтом. Дело в том, что килобайт — это отнюдь не тысяча байт, а 2 в 10-й степени, то есть 1024 байт.
Соответственно, мегабайт — это 1024 килобайт или 1048576 байт.
Гигабайт получается равен 1024 мегабайт или 1048576 килобайт или 1073741824 байт.
Для простоты можно использовать такую таблицу:
Для примера хочу привести вот такие цифры:
Стандартный лист А4 с печатным текстом занимает в средем около 100 килобайт
Обычная фотография на простой цифровой фотоаппарат — 5-8 мегабайт
Фотографии, сделанные на профессиональный фотоаппарат — 12-18 мегабайт
Музыкальный трек формата mp3 среднего качества на 5 минут — около 10 мегабайт.
Обычный фильм на 90 минут, сжатый в обычном качестве — 1,5-2 гигабайта
Тот же фильм в HD-качестве — от 20 до 40 гигабайт.
P.S.:
Теперь отвечу на вопросы, которые мне наиболее часто задают новички.
1. Сколько Килобит в Мегабите? Ответ — 1000 килобит (по системе СИ)
2. Сколько Килобайт в Мегабайте? Ответ — 1024 Килобайта
3. Сколько Килобит в Мегабайте? Ответ — 8192 килобита
4. Сколько Килобайт в Гигабайте? Ответ — 1 048 576 Килобайт.
Источник
Давайте разберемся, что же такое бит и байт. Бит, наименьшая единица, которая измеряет количество информации. Один содержит мало информации в отличие от группы битов. Для хранении информации используют всего два знака – цифры 0 и 1. Совокупность этих двух цифр называется двоичный код, а сами цифры принято называть двоичными цифрами или коротко битами. Компьютер различает 0 и 1 благодаря электрическим импульсам в электронных цепях. Если в цепи нет импульса – это цифра 0, если импульс есть, то это 1. Таким образом, в виде комбинации 0 и 1, внутри компьютера хранится абсолютно вся информация от фотографий до музыки. Наравне с понятием бита используется понятие байт.
Совокупность компьютерных данных из 8 бит называется байтом. 8 битов дают основу для представления символов, например буквы «А» и двоичной арифметики. То есть байт является командой битов, отвечающих за определенную деталь в файле. Каждый байт имеет в памяти компьютера уникальный адрес. По соглашению биты, и байты имеют нумерацию от 0 до 7 справа налево. Например: номер бита – 76543210, а значение его – 0 1 0 0 0 0 0 1 и в итоге, если передать это значение на принтер, там будет сгенерирована буква «А». Количество включенных битов в байте должно быть нечетно. Когда команда обращена к байту, компьютер проверяет этот байт и если число включенных битов четное, система выдает ошибку. Ошибка четности может быть результатом сбоя оборудования или случайным явлением, но это происходит очень редко.
Во время обработки данных, в компьютере по электронным цепям проходят электрические импульсы. Цепи состоят из проводников и электронных микро устройств, которые называются логическими вентилями. Импульсы, проходящие через эти вентили, могут «гаситься». Таким образом, обрабатываются данные. Объединяя логические вентили, создаются сложные комбинации, выполняющие операции – запоминают, сравнивают, складывают, сравнивают числа и прочее.
В кремниевых пластинках расположены электронные цепи. Каждая микросхема может содержать более миллиона цепей, от расположения зависит вид работы, которую они выполняют.
Микросхемы расположены на специальных пластинках, а именно на печатных платах. На самой плате напечатаны полоски, через которые проходит электричество к микросхемам. Металлические дорожки, которые называются шинами, передают байты, каждая шина содержит несколько таких дорожек. Одна дорожка передает один байт.
Шины делятся на три типа: шина данных, управления и адресная шина. Шина данных обменивается данными между процессором и устройствами ввода, между процессором и памятью компьютера. Инструкции от процессора ко всем узлам компьютера передаются по шине управления. С помощью адресной шины передается информация о местоположении или адресе данных.
Бит и байт это довольно маленькие величины, поэтому их используют с приставками кило, мега и гига. Давайте теперь поговорим о величине, которая измеряет скорость интернета. Скорость интернета, это количество отправляемой и получаемой информации вашим персональным компьютером в единицу времени. Качество единицы времени – секунда, а качество количества получаемой информации – килобит или мегабит. Например, если ваша скорость показывает 128 Kbps, значит, что ваше соединение пропускает 128 килобит что приравнивается к 16 килобайтам. Для того что бы узнать много это или мало воспользуйтесь тестами для определения скорости соединения с Интернетом.
Ярослав Бакланов
Присоединяйтесь у нашему сообществу, подписывайтесь и жмите палец вверх!
Источник
Перевод статьи Халида Азада — Understanding Big and Little Endian Byte Order
Проблемы с порядком байтов очень расстраивают, и я хочу избавить Вас от горя, которое довелось испытать мне. Вот ключевые тезы:
- Проблема: Компьютеры, как и люди, говорят на разных языках. Одни записывают данные “слева направо” другие “справа налево”. При этом каждое устройство отлично считывает собственные данные — проблемы начинаются, когда один компьютер сохраняет данные, а другой пытается эти данные считать.
- Решение: Принять некий общий формат (например, весь сетевой трафик передается в едином формате). Или всегда добавлять заголовок, описывающий формат хранения данных. Если считанный заголовок имеет обратный порядок, значит данные сохранены в другом формате и должны быть переконвертированы.
Числа и данные
Наиболее важная концепция заключается в понимании разницы между числами и данными, которые эти числа представляют. Число — это абстрактное понятия, как исчислитель чего-то. У Вас есть десять пальцев. Понятие “десять” не меняется, в зависимости от использованного представления: десять, 10, diez (испанский), ju (японский), 1010 (бинарное представление), Х (римские числа)… Все эти представления указывают на понятие “десяти”.
Сравним это с данными. Данные — это физическое понятие, просто последовательность битов и байтов, хранящихся на компьютере. Данные не имеют неотъемлемого значения и должны быть интерпретированы тем, кто их считывает.
Данные — это как человеческое письмо, просто набор отметок на бумаге. Этим отметкам не присуще какое-либо значение. Если мы видим линию и круг (например, |O), то можно интерпретировать это как “десять”. Но это лишь предположение, что считанные символы представляют число. Это могут быть буквы “IO” — название спутника Юпитера. Или, возможно, имя греческой богини. Или аббревиатура для ввода/вывода. Или чьи-то инициалы. Или число 2 в бинарном представлении (“10”). Этот список предположений можно продолжить. Дело в том, что один фрагмент данных (|O) может быть интерпретировано по разному, и смысл остается не ясен, пока кто-то не уточнит намерения автора.
Компьютеры сталкиваются с такой же проблемой. Они хранят данные, а не абстрактные понятия, используя при этом 1 и 0. Позднее они считывают эти 1 и 0 и пытаются воссоздать абстрактные понятия из набора данных. В зависимости от сделанных допущений, эти 1 и 0 могут иметь абсолютно разное значение.
Почему так происходит? Ну, вообще-то нет такого правила, что компьютеры должны использовать один и тот же язык, так же, как нет такого правила и для людей. Каждый компьютер одного типа имеет внутреннюю совместимость (он может считывать свои собственные данные), но нет никакой гарантии, как именно интерпретирует эти данные компьютер другого типа.
Основные концепции:
- Данные (биты и байты или отметки на бумаге) сами по себе не имеют смысла. Они должны быть интерпретированы в какое-то абстрактное понятие, например, число.
- Как и люди, компьютеры имеют различные способы хранения одного и того же абстрактного понятия (например, мы можем различными способами сказать “10”).
Храним числа как данные
К счастью, большинство компьютеров хранят данные всего в нескольких форматах (хотя так было не всегда). Это дает нам общую отправную точку, что делает жизнь немного проще:
- Бит имеет два состояния (включен или выключен, 1 или 0).
- Байт — это последовательность из 8 бит. Крайний левый бит в байте является старшим. То есть двоичная последовательность 00001001 является десятичным числом девять. 00001001 = (2^3 + 2^0 = 8 + 1 = 9).
- Биты нумеруются справа налево. Бит 0 является крайним правым и он наименьший. Бит 7 является крайним левым и он наибольший.
Мы можем использовать эти соглашения в качестве строительного блока для обмена данными. Если мы сохраняем и читаем данные по одному байту за раз, то этот подход будет работать на любом компьютере. Концепция байта одинаковая на всех машинах, понятие “байт 0” одинакова на всех машинах. Компьютеры также отлично понимают порядок, в котором Вы посылаете им байты — они понимают какой байт был прислан первым, вторым, третьим и т. д. “Байт 35” будет одним и тем же на всех машинах.
Так в чем же проблема — компьютеры отлично ладят с одиночными байтами, правда? Ну, все превосходно для однобайтных данных, таких как ASCII-символы. Однако, много данных используют для хранения несколько байтов, например, целые числа или числа с плавающей точкой. И нет никакого соглашения о том, в каком порядке должны хранится эти последовательности.
Пример с байтом
Рассмотрим последовательность из 4 байт. Назовем их W X Y и Z. Я избегаю наименований A B C D, потому что это шестнадцатеричные числа, что может немного запутывать. Итак, каждый байт имеет значение и состоит из 8 бит.
Имя байта W X Y Z
Позиция 0 1 2 3
Значение (hex) 0x12 0x34 0x56 0x78
Например, W — это один байт со значением 0х12 в шестнадцатеричном виде или 00010010 в бинарном. Если W будет интерпретироваться как число, то это будет “18” в десятеричной системе (между прочим, ничто не указывает на то, что мы должны интерпретировать этот байт как число — это может быть ASCII-символ или что-то совсем иное). Вы все еще со мной? Мы имеем 4 байта, W X Y и Z, каждый с различным значением.
Понимаем указатели
Указатели являются ключевой частью программирования, особенно в языке С. Указатель представляет собой число, являющееся адресом в памяти. И это зависит только от нас (программистов), как интерпретировать данные по этому адресу.
В языке С, когда вы кастите (приводите) указатель к конкретному типу (такому как char * или int *), это говорит компьютеру, как именно интерпретировать данные по этому адресу. Например, давайте объявим:
void *p = 0; // p указатель на неизвестный тип данных
// p нулевой указатель – не разыменовывать
char *c; // c указатель на один байт
Обратите внимание, что мы не можем получить из р данные, потому что мы не знаем их тип. р может указывать на цифру, букву, начало строки, Ваш гороскоп или изображение — мы просто не знаем, сколько байт нам нужно считать и как их интерпретировать.
Теперь предположим, что мы напишем:
c = (char *)p;
Этот оператор говорит компьютеру, что р указывает на то же место, и данные по этому адресу нужно интерпретировать как один символ (1 байт). В этом случае, с будет указывать на память по адресу 0, или на байт W. Если мы выведем с, то получим значение, хранящееся в W, которое равно шестнадцатеричному 0x12 (помните, что W — это полный байт). Этот пример не зависит от типа компьютера — опять же, все компьютеры одинаково хорошо понимают, что же такое один байт (в прошлом это было не всегда так).
Этот пример полезен, он одинаково работает на все компьютерах — если у нас есть указатель на байт (char *, один байт), мы можем проходить по памяти, считывая по одному байту за раз. Мы можем обратиться к любому месту в памяти, и порядок хранения байт не будет иметь никакого значения — любой компьютер вернет нам одинаковую информацию.
Так в чем же проблема?
Проблемы начинаются, когда компьютер пытается считать несколько байт. Многие типы данных состоят больше чем из одного байта, например, длинные целые (long integers) или числа с плавающей точкой. Байт имеет только 256 значений и может хранить числа от 0 до 255.
Теперь начинаются проблемы — если Вы читаете многобайтные данные, то где находится старший байт?
- Машины с порядком хранения от старшего к младшему (прямой порядок) хранят старший байт первым. Если посмотреть на набор байтов, то первый байт (младший адрес) считается старшим.
- Машины с порядком хранения от младшего к старшему (обратный порядок) хранят младший байт первым. Если посмотреть на набор байт, то первый байт будет наименьшим.
Такое именование имеет смысл, правда? Тип хранения от старшего к младшему подразумевает, что запись начинается со старшего и заканчивается младшим (Между прочим, английский вариант названий от старшего к младшего (Big-endian) и от младшего к старшему (Little-endian) взяты из книги “Путешествия Гулливера”, где лилипуты спорили о том, следует ли разбивать яйцо на маленьком конце (little-end) или на большом (big-end)). Иногда дебаты компьютеров такие же осмысленные 🙂
Повторюсь, порядок следования байтов не имеет значения пока Вы работаете с одним байтом. Если у Вас есть один байт, то это просто данные, которые Вы считываете и есть только один вариант их интерпретации (опять таки, потому что между компьютерами согласовано понятие одного байта).
Теперь предположим, что у нас есть 4 байта (WXYZ), которые хранятся одинаково на машинах с обоими типами порядка записи байтов. То есть, ячейка памяти 0 соответствует W, ячейка 1 соответствует X и т. д.
Мы можем создать такое соглашение, помня, что понятие “байт” является машинно-независимым. Мы можем обойти память по одному байту за раз и установить необходимые значения. Это будет работать на любой машине.
c = 0; // указывает на позицию 0 (не будет работать на реальной машине!)
*c = 0x12; // устанавливаем значение W
c = 1; // указывает на позицию 1
*c = 0x34; // устанавливаем значение X
… // то же повторяем для Y и Z
Такой код будет работать на любой машине и успешно установит значение байт W, X, Y и Z расположенных на соответствующих позициях 0, 1, 2 и 3.
Интерпретация данных
Теперь давайте рассмотрим пример с многобайтными данными (наконец-то!). Короткая сводка: “short int” это 2-х байтовое число (16 бит), которое может иметь значение от 0 до 65535 (если оно беззнаковое). Давайте используем его в примере.
short *s; // указатель на short int (2 байта)
s = 0; // указатель на позицию 0; *s это значение
Итак, s это указатель на short int, и сейчас он указывает на позицию 0 (в которой хранится W). Что произойдет, когда мы считаем значение по указателю s?
- Машина с прямым порядком хранения: Я думаю, short int состоит из двух байт, а значит я считаю их. Позиция s это адрес 0 (W или 0х12), а позиция s + 1 это адрес 1 (X или 0х34). Поскольку первый байт является старшим, то число должно быть следующим 256 * байт 0 + байт 1 или 256 * W + X, или же 0х1234. Я умножаю первый байт на 256 (2^8) потому что его нужно сдвинуть на 8 бит.
- Машина с обратным порядком хранения: Я не знаю что курит мистер “От старшего к младшему”. Я соглашусь, что short int состоит из 2 байт и я считаю их точно также: позиция s со значение 0х12 и позиция s + 1 со значением 0х34. Но в моем мире первым является младший байт! И число должно быть байт 0 + 256 * байт 1 или 256 * X + W, или 0х3412.
Обратите внимание, что обе машины начинали с позиции s и читали память последовательно. Не никакой путаницы в том, что значит позиция 0 и позиция 1. Как и нет никакой путаницы в том, что являет собой тип short int.
Теперь Вы видите проблему? Машина с порядком хранения от старшего к младшему считает, что s = 0x1234, в то время как машина с порядком хранения от младшего к старшему думает, что s = 0x3412. Абсолютно одинаковые данные дают в результате два совершенно разных числа.
И еще один пример
Давайте для “веселья” рассмотрим еще один пример с 4 байтовым целым:
int *i; // указатель на int (4 байты 32-битовой машине)
i = 0; // указывает на позицию 0, а *i значение по этому адресу
И опять мы задаемся вопросом: какое значение хранится по адресу i?
- Машина с прямым порядком хранения: тип int состоит из 4 байт и первый байт является старшим. Считываю 4 байта (WXYZ) из которых старший W. Полученное число: 0х12345678.
- Машина с обратным порядком хранения: несомненно, int состоит из 4 байт, но старшим является последний. Так же считываю 4 байта (WXYZ), но W будет расположен в конце — так как он является младшим. Полученное число: 0х78563412.
Одинаковые данные, но разный результат — это не очень приятная вещь.
Проблема NUXI
Проблему с порядком байт иногда называют проблемой NUXI: слово UNIX, сохраненное на машинах с порядком хранения от старшего к младшему, будет отображаться как NUXI на машинах с порядком от младшего к старшему.
Допустим, что мы собираемся сохранить 4 байта (U, N, I, и X), как два short int: UN и IX. Каждая буква занимает целый байт, как в случае с WXYZ. Для сохранения двух значений типа short int напишем следующий код:
short *s; // указатель для установки значения переменной типа short
s = 0; // указатель на позицию 0
*s = UN; // устанавливаем первое значение: U * 256 + N (вымышленный код)
s = 2; // указатель на следующую позицию
*s = IX; // устанавливаем второе значение: I * 256 + X
Этот код не является специфичным для какой-то машины. Если мы сохраним значение “UN” на любой машине и считаем его обратно, то обратно получим тоже “UN”. Вопрос порядка следования байт не будет нас волновать, если мы сохраняем значение на одной машине, то должны получить это же значение при считывании.
Однако, если пройтись по памяти по одному байту за раз (используя трюк с char *), то порядок байт может различаться. На машине с прямым порядком хранения мы увидим:
Byte: U N I X
Location: 0 1 2 3
Что имеет смысл. “U” является старшим байтом в “UN” и соответственно хранится первым. Такая же ситуация для “IX”, где “I” — это старший байт и хранится он первым.
На машине с обратным порядком хранения мы скорее всего увидим:
Byte: N U X I
Location: 0 1 2 3
Но и это тоже имеет смысл. “N” является младшим байтом в “UN” и значит хранится он первым. Опять же, хотя байты хранятся в “обратном порядке” в памяти, машины с порядком хранения от младшего к старшему знают что это обратный порядок байт, и интерпретирует их правильно при чтении. Также, обратите внимание, что мы можем определять шестнадцатеричные числа, такие как 0x1234, на любой машине. Машина с обратным порядком хранения байтов знает, что Вы имеете в виду, когда пишите 0x1234 и не заставит Вас менять значения местами (когда шестнадцатеричное число отправляется на запись, машина понимает что к чему и меняет байты в памяти местами, скрывая это от глаз. Вот такой трюк.).
Рассмотренный нами сценарий называется проблемой “NUXI”, потому что последовательность “UNIX” интерпретируется как “NUXI” на машинах с различным порядком хранения байтов. Опять же, эта проблема возникает только при обмене данными — каждая машина имеет внутреннюю совместимость.
Обмен данными между машинами с различным порядком хранения байтов
Сейчас компьютеры соединены — прошли те времена, когда машинам приходилось беспокоиться только о чтении своих собственных данных. Машинам с различным порядком хранения байтов нужно как-то обмениваться данными и понимать друг друга. Как же они это делают?
Решение 1: Использовать общий формат
Самый простой подход состоит в согласовании с общим форматом для передачи данных по сети. Стандартным сетевым является порядок от старшего к младшему, но некоторые люди могут расстроиться, что не победил порядок от младшего к старшему, поэтому просто назовем его “сетевой порядок”.
Для конвертирования данных в соответствии с сетевым порядком хранения байтов, машины вызывают функцию hton() (host-to-network). На машинах с прямым порядком хранения эта функция не делает ничего, но мы не будем говорить здесь об этом (это может разозлить машины с обратным порядком хранения 🙂 ).
Но важно использовать функцию hton() перед отсылкой данных даже если Вы работаете на машине с порядком хранения от старшего к младшему. Ваша программа может стать весьма популярной и будет скомпилирована на различных машинах, а Вы ведь стремитесь к переносимости своего кода (разве не так?).
Точно также существует функция ntoh() (network-to-host), которая используется для чтения данных из сети. Вы должны использовать ее, чтобы быть уверенными, что правильно интерпретируете сетевые данные в формат хоста. Вы должны знать тип данных, которые принимаете, чтобы расшифровать их правильно. Функции преобразования имеют следующий вид:
htons() – “Host to Network Short”
htonl() – “Host to Network Long”
ntohs() – “Network to Host Short”
ntohl() – “Network to Host Long”
Помните, что один байт — это один байт и порядок не имеет значения.
Эти функции имеют критическое значение при выполнении низкоуровневых сетевых операций, таких как проверка контрольной суммы IP-пакетов. Если Вы не понимаете сути проблемы с порядком хранения байтов, то Ваша жизнь будет наполнена болью — поверьте мне на слово. Используйте функции преобразования и знайте, зачем они нужны.
Решение 2: Использования маркера последовательности байтов (Byte Order Mark — BOM)
Этот подход подразумевает использование некого магического числа, например 0xFEFF, перед каждым куском данных. Если Вы считали магическое число и его значение 0xFEFF, значит данные в том же формате, что и у Вашей машины и все хорошо. Если Вы считали магическое число и его значение 0xFFFE, это значит, что данные были записаны в формате, отличающемся от формата вашей машины и Вы должны будете преобразовать их.
Нужно отметить несколько пунктов. Во-первых, число не совсем магическое, как известно программисты часто используют этот термин для описания произвольно выбранных чисел (BOM может быть любой последовательностью различных байтов). Такая пометка называется маркером последовательности байтов потому что показывает в каком порядке данные были сохранены.
Во-вторых, BOM добавляет накладные расходы для всех передаваемых данных. Даже в случае передачи 2 байт информации Вы должны добавлять к ним 2 байта маркера BOM. Пугающе, не так ли?
Unicode использует BOM, когда сохраняет многобайтные данные (некоторые кодировки Unicode могут иметь по 2, 3 и даже 4 байта на символ). XML позволяет избежать этой путаницы, сохраняя данные сразу в UTF-8 по умолчанию, который сохраняет информацию Unicode по одному байту за раз. Почему это так круто?
Повторяю в 56-й раз — потому что проблема порядка хранения не имеет значения для единичных байт.
Опять же, в случае использования BOM может возникнуть другие проблемы. Что, если Вы забудете добавить BOM? Будете предполагать, что данные были отправлены в том же формате, что и Ваши? Прочитаете данные и, увидев что они “перевернуты” (что бы это не значило), попытаетесь преобразовать их? Что, если правильные данные случайно будут содержать неправильный BOM? Эти ситуации не очень приятные.
Почему вообще существует эта проблема? Нельзя ли просто договориться?
Ох, какой же это философский вопрос. Каждый порядок хранения байтов имеет свои преимущества. Машины с порядком следования от младшего к старшему позволяют читать младший байт первым, не считывая при этом остальные. Таким образом можно легко проверить является число нечетным или четным (последний бит 0), что очень здорово, если Вам необходима такая проверка. Машины с порядком от старшего к младшему хранят данные в памяти в привычном для человека виде (слева направо), что упрощает низкоуровневую отладку.
Так почему же все просто не договорятся об использовании одной из систем? Почему одни компьютеры пытаются быть отличными от других? Позвольте мне ответить вопросом на вопрос: почему не все люди говорят на одном языке? Почему в некоторых языках письменность слева направо, а у других справа налево?
Иногда системы развиваются независимо, а в последствии нуждаются во взаимодействии.
Эпилог: Мысли на прощание
Вопросы с порядком хранения байтов являются примером общей проблемы кодирования — данные должны представлять собой абстрактные понятия, и позднее это понятие должно быть создано из данных. Эта тема заслуживает отдельной статьи (или серии статей), но Вы дол