Обратный порядок считывания байтов в массиве
От: plusovik  
Дата: 12.06.22 19:38
Оценка: :))) :))) :))
Здравствуйте, почему байты считываются в обратном порядке?
Проверял на MSVC ( x86, x64 ) и на gcc, вывод один и тот же.
Читал, что иногда байты считываются в обратном порядке, но почему и где про это прочесть?
С какой целью производится такое странное считывание?

#include <iostream>
#include <inttypes.h>

int main()
{
    uint16_t x[ 9U ] = { 0, 0x11AA, 0x21ABU, 0x33CCU, 0x41D1U, 0x55EEU, 0x66FFU, 0xABCDU, 0xFEDCU };
    printf( "%llu, %llu, %llu, %llu, %llu\n\n",
        sizeof( int ),
        sizeof( uint8_t ), sizeof( uint16_t ),
        sizeof( uint32_t ), sizeof( uint64_t ) );

    uint8_t  a08 = *static_cast<uint8_t* >( static_cast<void*>( &x[2] ) );
    uint16_t a16 = *static_cast<uint16_t*>( static_cast<void*>( &x[2] ) );
    uint32_t a32 = *static_cast<uint32_t*>( static_cast<void*>( &x[2] ) );
    uint64_t a64 = *static_cast<uint64_t*>( static_cast<void*>( &x[2] ) );

    printf("%llu, a08: %lX\n",  sizeof( a08 ), static_cast<long int>( a08 ) );
    printf("%llu, a16: %lX\n",  sizeof( a16 ), static_cast<long int>( a16 ) );
    printf("%llu, a32: %lX\n",  sizeof( a32 ), static_cast<long int>( a32 ) );
    printf("%llu, a64: %llX\n", sizeof( a64 ), static_cast<long long int>( a64 ) );

    return 0;
}

// Output:
// 4, 1, 2, 4, 8
// 1, a08: AB
// 2, a16: 21AB
// 4, a32: 33CC21AB
// 8, a64: 55EE41D133CC21AB

// А я ожидал следующий Output:
// 4, 1, 2, 4, 8
// 1, a08: 21
// 2, a16: 21AB
// 4, a32: 21AB33CC
// 8, a64: 21AB33CC41D155EE
Отредактировано 12.06.2022 19:59 plusovik . Предыдущая версия . Еще …
Отредактировано 12.06.2022 19:41 plusovik . Предыдущая версия .
Re: Обратный порядок считывания байтов в массиве
От: Stanislav V. Zudin Россия  
Дата: 12.06.22 19:49
Оценка: +2
Здравствуйте, plusovik, Вы писали:

P>Здравствуйте, почему байты считываются в обратном порядке?

P>Проверял на MSVC ( x86, x64 ) и на gcc, вывод один и тот же.
P>Читал, что иногда байты считываются в обратном порядке, но почему и где про это прочесть?

Это называется Endianness — порядок байт в слове.
У интела принята Little-endian (младший байт идет первым), у HPUX (если склероз не подводит) — Big-endian (первый — старший байт).
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Обратный порядок считывания байтов в массиве
От: plusovik  
Дата: 12.06.22 19:56
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Это называется Endianness — порядок байт в слове.

SVZ>У интела принята Little-endian (младший байт идет первым), у HPUX (если склероз не подводит) — Big-endian (первый — старший байт).

В данном примере вроде байты читаются как и ожидаешь, слева направо, а элементы массива при выходе за границу — в обратном порядке.
Почему так?
Re[3]: Обратный порядок считывания байтов в массиве
От: T4r4sB Россия  
Дата: 12.06.22 20:07
Оценка:
Здравствуйте, plusovik, Вы писали:

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

P>Почему так?

Ну сначала младшие байты, потом старшие.
Re[3]: Обратный порядок считывания байтов в массиве
От: Stanislav V. Zudin Россия  
Дата: 12.06.22 20:08
Оценка: +1
Здравствуйте, plusovik, Вы писали:

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

P>Почему так?

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

На твоей машине LE — это видно, если получить первый байт у инт16.

Знание о Endianness пригодится при передаче двоичных данных по сети и при работе с отдельными битами/байтами в кросс-платформенных приложениях.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Обратный порядок считывания байтов в массиве
От: plusovik  
Дата: 12.06.22 20:15
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>При выходе за границу массива ты читаешь мусор, казалось бы, это очевидно.
SVZ>Или я тебя неправильно понял?
Там не совсем мусор, а проинициализированные байты


Здравствуйте, T4r4sB, Вы писали:
TB>Ну сначала младшие байты, потом старшие.
Судя по всему, сначала читаются младшие биты, тогда понятно, почему a08 = AB.
А почему a32: 33CC21AB, а не a32: 21AB33CC ?
Отредактировано 12.06.2022 20:16 plusovik . Предыдущая версия .
Re[5]: Обратный порядок считывания байтов в массиве
От: T4r4sB Россия  
Дата: 12.06.22 20:20
Оценка:
Здравствуйте, plusovik, Вы писали:
P>А почему a32: 33CC21AB, а не a32: 21AB33CC ?

Потому что сначала считался a[2] это 21AB, а потом считался a[3] это 33СС, и то, что считалось позже, идёт в старшие байты
Элементы массива всегда идут в одном и том же порядке на любой архитектуре.
Re[5]: Обратный порядок считывания байтов в массиве
От: Bill Baklushi СССР  
Дата: 12.06.22 20:32
Оценка:
plusovik:

P>Судя по всему, сначала читаются младшие биты, тогда понятно, почему a08 = AB.

Не "читаются младшие байты", а размещаются.
Порядок байтов в слове, слов в двойном слове и т.д. — это и есть endianness.

P>А почему a32: 33CC21AB, а не a32: 21AB33CC ?

Возьми тетрадку в клеточку, разрисуй и сразу навсегда разберешься.
Объединяйтесь, либералы, для рытья каналов!
Re[6]: Обратный порядок считывания байтов в массиве
От: plusovik  
Дата: 12.06.22 20:52
Оценка: -1 :)
Здравствуйте, T4r4sB, Вы писали:
TB>Потому что сначала считался a[2] это 21AB, а потом считался a[3] это 33СС, и то, что считалось позже, идёт в старшие байты
TB>Элементы массива всегда идут в одном и том же порядке на любой архитектуре.
Кажется, понял: младшие байты расположены левее, они же считываются первыми.
По сути в памяти элемент 21AB расположен, как BA12, а элемент 33СС расположен, как СС33, а "вместе" они расположены, как BA12СС33.

Тогда при манипуляциях с указателями читаем, словно ими не манипулирвали, и записываем первые прочитанные байты в младшие и далее по старшинству. После чего из BA12СС33 получаем 33CC21AB ( просто прочли справа налево BA12СС33 ).

Я правильно понял?
Только непонятно, зачем так располагать байты и почему именно байты так странно записываются, а не сразу биты.
Отредактировано 12.06.2022 20:54 plusovik . Предыдущая версия .
Re[7]: Обратный порядок считывания байтов в массиве
От: T4r4sB Россия  
Дата: 12.06.22 20:57
Оценка:
Здравствуйте, plusovik, Вы писали:

P>Я правильно понял?


Да

P>Только непонятно, зачем так располагать байты


Это удобно, когда у тебя есть uint32_t число, которое меньше, чем 65536. И тогда если по тому же адресу прочитать uint16_t, то получится такое же значение

P>и почему именно байты так странно записываются, а не сразу биты.


А как ты определишь порядок битов?
Re: Обратный порядок считывания байтов в массиве
От: AleksandrN Россия  
Дата: 12.06.22 21:03
Оценка: -2 :)
Здравствуйте, plusovik, Вы писали:

P>Читал, что иногда байты считываются в обратном порядке, но почему и где про это прочесть?


https://en.wikipedia.org/wiki/Endianness
https://habr.com/ru/post/233245/

P>С какой целью производится такое странное считывание?


В Intel 8088 были 16-разрядные регистры, но 8-разрядная шина данных.
В регистрах порядок байт — big-endian, а в памяти — little-endian, потому, что разработчикам процессора так было проще из памяти в регистры данные записывать. А потом такой порядок сохранился с целью обратной совместимости.
Re[8]: Обратный порядок считывания байтов в массиве
От: plusovik  
Дата: 12.06.22 21:13
Оценка:
Здравствуйте, T4r4sB, Вы писали:
P>>Я правильно понял?
TB>Да
Спасибо за объяснения, остальным тоже.

TB>А как ты определишь порядок битов?

Например, в моём примере вместо 21AB в памяти записали BA12, а потом прочли, начиная заполнять младшие биты.

В двоичной записи это 21AB — это 0010 0001 1010 1011.
Почему тогда его записали как BA12 1011 1010 0001 0010,
а не как 1101 0101 1000 0100 ( D584 )?


P.S.
Завтра собираюсь прочесть то, что написал AleksandrN, наверное, в той ссылке есть ответ на данный вопрос.
AN>https://en.wikipedia.org/wiki/Endianness
AN>https://habr.com/ru/post/233245/

Стало понятнее, ещё раз спасибо тем, кто отвечал.
Отредактировано 12.06.2022 21:22 plusovik . Предыдущая версия . Еще …
Отредактировано 12.06.2022 21:16 plusovik . Предыдущая версия .
Re[9]: Обратный порядок считывания байтов в массиве
От: T4r4sB Россия  
Дата: 12.06.22 21:27
Оценка: +1
Здравствуйте, plusovik, Вы писали:

P>В двоичной записи это 21AB — это 0010 0001 1010 1011.

P>Почему тогда его записали как BA12 1011 1010 0001 0010,
P>а не как 1101 0101 1000 0100 ( D584 )?

Откуда ты знаешь, как его записали? Это нельзя никак определить, потому что нельзя адресовать отдельные биты в байте.
Всё, что ты можешь сказать — его считали так же, как записали.
Re[10]: Обратный порядок считывания байтов в массиве
От: Stanislav V. Zudin Россия  
Дата: 12.06.22 21:35
Оценка:
Здравствуйте, T4r4sB, Вы писали:

P>>В двоичной записи это 21AB — это 0010 0001 1010 1011.

P>>Почему тогда его записали как BA12 1011 1010 0001 0010,
P>>а не как 1101 0101 1000 0100 ( D584 )?

TB>Откуда ты знаешь, как его записали? Это нельзя никак определить, потому что нельзя адресовать отдельные биты в байте.

TB>Всё, что ты можешь сказать — его считали так же, как записали.

Подтверждение тому, что биты не переворачиваются, можно найти в реализации функций htons, ntohs, htonl, ntohl — переставляются только байты.
_____________________
С уважением,
Stanislav V. Zudin
Re[9]: Обратный порядок считывания байтов в массиве
От: Андрей Тарасевич Беларусь  
Дата: 13.06.22 05:36
Оценка: +1 -1
Здравствуйте, plusovik, Вы писали:

P>В двоичной записи это 21AB — это 0010 0001 1010 1011.

P>Почему тогда его записали как BA12 1011 1010 0001 0010,
P>а не как 1101 0101 1000 0100 ( D584 )?

Понятие "порядка" ("endianness") применимо только к индивидуально адресуемым единицам в рамках некоего составного агрегата, напр. к отдельным 8-битным байтам в 64-битном слове. То есть речь в данном случае идет о том, как порядок значимости байтов в слове соотносится с их порядком в адресах памяти.

Биты не являются индивидуально адресуемыми, поэтому к ним понятие "endianness" не применимо вообще. У битов нет "порядка в памяти". Поэтому не ясно, с чего это вдруг вы собрались их переворачивать. "Переворачивать" относительно чего?

P.S. На многих платформах существуют машинные команды, которые действительно "адресуют", т.е. локально нумеруют индивидуальные биты в байте. Но там везде действует единое соглашение: младшие по значимости биты имеют младшие номера. То есть нумерация битов всегда и везде подчиняется правилам условного "little-endian" и никакого "плюрализма мнений" не допускается.
Best regards,
Андрей Тарасевич
http://files.rsdn.org/2174/val.gif
Re[9]: Обратный порядок считывания байтов в массиве
От: galileo Земля  
Дата: 15.06.22 22:25
Оценка:
Здравствуйте, plusovik, Вы писали:

потому что биты в байте во всех системах пишутся одинакого
а байты в инте — нет
Re[2]: Обратный порядок считывания байтов в массиве
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.07.22 10:09
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

P>>Здравствуйте, почему байты считываются в обратном порядке?

P>>Проверял на MSVC ( x86, x64 ) и на gcc, вывод один и тот же.
P>>Читал, что иногда байты считываются в обратном порядке, но почему и где про это прочесть?

SVZ>Это называется Endianness — порядок байт в слове.

SVZ>У интела принята Little-endian (младший байт идет первым), у HPUX (если склероз не подводит) — Big-endian (первый — старший байт).

HP-UX это ОС, а не ISA. Живые архитектуры с big-endian это SPARC, IBM System/Z (самая живучая и актуальная сейчас).
Re[8]: Обратный порядок считывания байтов в массиве
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.07.22 10:11
Оценка:
Здравствуйте, T4r4sB, Вы писали:

P>>Только непонятно, зачем так располагать байты


TB>Это удобно, когда у тебя есть uint32_t число, которое меньше, чем 65536. И тогда если по тому же адресу прочитать uint16_t, то получится такое же значение


Да, очень удобно делать ошибки с молчаливым усечением значения, которые максимально долго не будут ловиться тестами.
Re[9]: Обратный порядок считывания байтов в массиве
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.07.22 10:18
Оценка:
Здравствуйте, plusovik, Вы писали:

TB>>А как ты определишь порядок битов?

P>Например, в моём примере вместо 21AB в памяти записали BA12, а потом прочли, начиная заполнять младшие биты.

Перестановка порядка идёт блоками размером в байт. Поэтому 21AB при обратном порядке будет прочтено как AB21, а не BA12.
Чтобы переставлять ещё и полубайты в байте, нужны спец. меры.

Я с этим недавно столкнулся в понятии PLMN id (идентификатор мобильной сети): в актуальных стандартах его упаковывают в 3 байта в BCD (binary coded decimal) формате с переставленными полубайтами.
Например MCC=123, MNC=45 будет представлено 3 байтами: 0x21 0xf3 0x54 ('f' тут заполнитель для двузначного номера сети). Заметим, что MNC=45 и MNC=045 это разные случаи(!), во втором будет представление 0x21 0x03 0x54.

Так что, возможно, у вас ещё всё впереди

P>В двоичной записи это 21AB — это 0010 0001 1010 1011.

P>Почему тогда его записали как BA12 1011 1010 0001 0010,
P>а не как 1101 0101 1000 0100 ( D584 )?

Разворот порядка битов тоже имеет значение в некоторых случаях: тут
Автор: netch80
Дата: 06.05.17
.
Re[10]: Обратный порядок считывания байтов в массиве
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.07.22 10:36
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>P.S. На многих платформах существуют машинные команды, которые действительно "адресуют", т.е. локально нумеруют индивидуальные биты в байте. Но там везде действует единое соглашение: младшие по значимости биты имеют младшие номера. То есть нумерация битов всегда и везде подчиняется правилам условного "little-endian" и никакого "плюрализма мнений" не допускается.


Вы явно не всё знаете. На System/Z адресация в соответствующих командах (например, RISBG) сделана так, что 0 — старший. Это последовательная big endian архитектура (и самая живучая из них на сейчас). Возможно, есть и другие (облом искать), одного контрпримера достаточно.

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

АТ>Биты не являются индивидуально адресуемыми, поэтому к ним понятие "endianness" не применимо вообще. У битов нет "порядка в памяти".


Он появляется, когда надо рассматривать сквозной порядок битов между разными байтами, , я рядом писал уже про особенности
Автор: netch80
Дата: 06.05.17
работы с bitset. Это точно так же обсуждено со всех сторон в основополагающем документе (именно тут был введён термин endianness), там явно упоминается, что может быть bit order, byte order, word order... и какие могут быть проблемы от их рассогласования.

AT> Поэтому не ясно, с чего это вдруг вы собрались их переворачивать. "Переворачивать" относительно чего?


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