Russian Qt Forum
Ноябрь 24, 2024, 03:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Структуры и байты  (Прочитано 4501 раз)
Anarion
Гость
« : Октябрь 29, 2010, 19:02 »

Доброго всем времени суток.
Извиняюсь, если вопрос не совсем относится к Qt, но может быть вы сможете сказать чего я не понимаю.
В общем объявил структуру:
Код:
//Прагму использовал для упаковки. чтобы структура занимала 10 байт в соответствии с суммой всех полей. Без прагмы 12 байт.
#pragma pack(push, 1)
struct SNAC_HDR
{
  unsigned short int FamilyID;
  unsigned short int SubTypeID;
  unsigned short int Flags;
  //unsigned char Flags[2];
  unsigned long int RequestID;
};
#pragma pack(pop)

Далее в теле программы:
   
Код:
SNAC_HDR snac; //создаю объект структуры

    unsigned char b[4] = {4,3,2,1}; //создаю массив символов
    memset(&snac,0,4); //устанавливаю в 0 первые 4 байта структуры
    memcpy(&snac,&b,4); //заполняю их из массива

    unsigned char d[4]; //объявляю еще один массив символов
    memcpy(&d,&snac,4); //копирую из адреса структуры в новый массив
    //вывожу посимвольно для проверки, должно быть 4 3 2 1
    for (int i=0; i<4; i++)
    {
      qDebug() << " i [" << i << "] " << d[i];
    }

    qDebug() << "0" << &snac << &snac.FamilyID << &snac.SubTypeID << &snac.Flags; //вывожу адреса полей для проверки занимаемых байт
    qDebug() << "1" << snac.FamilyID << snac.SubTypeID; //вывожу поля "как есть" в отладчике
    qDebug() << "2" << (unsigned short int)snac.FamilyID << (unsigned short int)snac.SubTypeID; //то же с преобразованием к типу полей
    qDebug() << "3" << (unsigned char)snac.FamilyID << (unsigned char)snac.SubTypeID; //то же с преобразованием к символьному типу


В результате в отладчике получаю следующее:
Код:
i [ 0 ]  4 
i [ 1 ]  3
i [ 2 ]  2
i [ 3 ]  1

0 0x22c7b6 0x22c7b6 0x22c7b8 0x22c7ba
1 772 258
2 772 258
3 4 2

Видно, что поля установлены правильно, и сами поля (судя по адресу) занимаю 2 байта. Но вот значения полей озадачивают (772 и 258).
Не могу понять откуда они берутся. Если посмотреть внимательно, то можно вывести, что 772 (10) = 304 (16), а 258 (10) = 102 (16).
Т.е. во-первых переставляются байты, во-вторых между ними появляется 0 и вообще получается, что значение полей определяется 3 битами, хотя по адресам их 2. Не пойму, куда копать. С одной стороны значения байтов правильные, с другой стороны значения самих полей, выводимые в qDebug() неправильные.
Подскажите пожалуйста, где неправ. Заранее благодарен.
Записан
BlackTass
Гость
« Ответ #1 : Октябрь 29, 2010, 20:12 »

Ну наверно начать надо с того, что все же у нас данные хранятся в двоичной системе и один байт это 8-значное двоичное число, либо 2-значное hex число. То есть все же 0x102 это два байта, а не три (0x01 и 0x02).
По поводу перестановки байт. Советую почитать в вики про big-endian и little-endian. Вопрос думаю сразу отпадет.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Октябрь 29, 2010, 20:39 »

Ну наверно начать надо с того, что все же у нас данные хранятся в двоичной системе и один байт это 8-значное двоичное число, либо 2-значное hex число. То есть все же 0x102 это два байта, а не три (0x01 и 0x02).
По поводу перестановки байт. Советую почитать в вики про big-endian и little-endian. Вопрос думаю сразу отпадет.
Да все правильно, в байты лезть - получить по ушам с endian. Но так ли уж это очевидно и "само-собой"? Напр. будет ли корректно (однозначно) работать такое на обоих endian:

Код:
double d = 3.14159;
char test1 = *((long long *) &d) << 48;
char test2 = *((int *) &d) & 0xFF;
И почему?
Записан
Anarion
Гость
« Ответ #3 : Октябрь 29, 2010, 21:22 »

Спасибо большое, ситуация вроде как начала прояснятся. Получается, что для правильного отображения мне сначала нужно поменять местами старший и младший байты, но для передачи по сети оставить как есть?
Записан
developer
Гость
« Ответ #4 : Октябрь 30, 2010, 13:17 »

Да
Записан
BlackTass
Гость
« Ответ #5 : Октябрь 30, 2010, 20:25 »

Да
На x86 да, а, например, на Эльбрусах (которые SPARC) не нужно менять местами.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.15 секунд. Запросов: 23.