Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > как запаковать в пакет (комбинированный байт) ???


Автор: princessik 13.6.2015, 14:40
Здравствуйте, неожиданно возникла потребность упаковать в передаваемый пакет два числа по этой схеме:
user posted image
в совмещенном бите находятся самые младшие разряды обоих чисел, т.е если есть  числа
1111 1111 1111 0000 и 0000 0000 0000 1111 то в совмещенном бите будут
раздяды 0000 первого числа и разряды 1111 второго числа

подскажите пожалуйста в чем ошибка??
Код

            packet[0] = Byte(m_sendData.latitude >> 8 & 0xFF);
            packet[1] = Byte(m_sendData.latitude >> 16 & 0xFF);
            packet[2] = Byte(m_sendData.latitude >> 24 & 0xFF);
            packet[3] = Byte((m_sendData.latitude << 5 & 0xFF) | (1 << 4) | (m_sendData.longitude & 0x0F));
            packet[4] = Byte(m_sendData.longitude >> 4 & 0xFF);
            packet[5] = Byte(m_sendData.longitude >> 8 & 0xFF);
            packet[6] = Byte(m_sendData.longitude >> 16 & 0xFF);


долгота вроде правильно присылается, а вот с широтой что-то не то...

Автор: feodorv 14.6.2015, 00:02
Цитата(princessik @  13.6.2015,  14:40 Найти цитируемый пост)
            packet[5] = Byte(m_sendData.longitude >> 12 & 0xFF);
            packet[6] = Byte(m_sendData.longitude >> 20 & 0xFF);



Цитата(princessik @  13.6.2015,  14:40 Найти цитируемый пост)
долгота вроде правильно присылается

Есть сомнение:
Цитата(princessik @  13.6.2015,  14:40 Найти цитируемый пост)
m_sendData.latitude << 5

В результате бит номер три (если отсчитывать от нуля) тихо исчезает со сцены...


Не понятна роль единицы.


Цитата(princessik @  13.6.2015,  14:40 Найти цитируемый пост)
в совмещенном бите

В совмещённом байте?

Автор: princessik 14.6.2015, 09:33
да, байте, опечатка
насчет единицы не знаю её роль, но а так не было студии под рукой чтобы проверить свой код, спасибо большое

Автор: princessik 16.6.2015, 10:36
       получается,  теперь правильно?
Код

            packet[0] = Byte(m_sendData.latitude >> 5 & 0xFF);
            packet[1] = Byte(m_sendData.latitude >> 13 & 0xFF);
            packet[2] = Byte(m_sendData.latitude >> 21 & 0xFF);
            packet[3] = Byte((m_sendData.latitude << 5 & 0xFF) | (1 << 4) | (m_sendData.longitude & 0x0F));
            packet[4] = Byte(m_sendData.longitude >> 4 & 0xFF);
            packet[5] = Byte(m_sendData.longitude >> 12 & 0xFF);
            packet[6] = Byte(m_sendData.longitude >> 20 & 0xFF);

Автор: baldina 16.6.2015, 11:04
princessik, здесь проще использовать битовые поля

Код

typedef unsigned char byte;

#pragma pack(push, 1)
union {
    byte packet[7];
    struct {
       unsigned latitude: 27;
       unsigned one: 1;
       unsigned longitude: 28;
    } data;
} u;
#pragma pack(pop)
...
u.data.latitude = m_sendData.latitude;
u.data.one = 1;
u.data.longitude = m_sendData.longitude;
...
send(u.packet);


Автор: bsa 16.6.2015, 12:26
baldina, вот только что делать в случает машин с другим порядком байт в словах?

Автор: princessik 16.6.2015, 12:53
спасибо, но..каким образом data соответствует packet, это же получаются два разных поля? я как-то упаковывала в юнионы, там действительно есть свои подводные камни,
а со сдвигами всё-таки что не так?

Автор: feodorv 16.6.2015, 14:03
Цитата(princessik @  16.6.2015,  12:53 Найти цитируемый пост)
а со сдвигами всё-таки что не так?

У Вас три бита откусываются на совмещённый байт. А здесь
Цитата(princessik @  16.6.2015,  10:36 Найти цитируемый пост)
            packet[0] = Byte(m_sendData.latitude >> 5 & 0xFF);
почему-то считается, что их пять...

Автор: baldina 16.6.2015, 14:07
bsa, можно http://habrahabr.ru/post/121811/, например
в случае с явными битовыми операциями это ведь тоже учесть придется. а искать блох в семи копипастах дело имхо неблагодарное. поэтому отвечать на вопрос
Цитата(princessik @  16.6.2015,  12:53 Найти цитируемый пост)
а со сдвигами всё-таки что не так?

мне элементарно лень

Цитата(princessik @  16.6.2015,  12:53 Найти цитируемый пост)
каким образом data соответствует packet

это union, так что data и packet занимают одну область памяти. получаются два разных представления одних и тех же данных, что вам и нужно.

Автор: princessik 16.6.2015, 14:18
       то ли я чего то не понимаю, вообщем порядок должен быть таков что в 4м байте идут самые старшие биты, потом средние в 0м, 1м и самые младшие биты в 2м и со второй переменной точно так же
поэтому можно ли union из примера использовать??



Автор: baldina 16.6.2015, 22:54
big-endian? логично)))
union, и вообще любая структура, используют текущий для данной платформы порядок байт. поэтому, например, среднее слово (куда попадает единица между координатами) будет "перевернуто" даже при использовании битовых полей на платформе x86 (little endian).
для преобразования в порядок big-endian (от старшего к младшему), который обычно используется для сетевой передачи, на любой платформе есть функции htonl, htons и тп. или см. мою ссылку выше.

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)