Упаковка и распаковка битов.

Deep Sky
Offline
Зарегистрирован: 12.10.2014

Решил создать такую тему так как кроме битовых сдвигов ничего не нашел в инете.

например 

int i = 255;

как мне распаковать 255 на 8 boolean тегов?

boolean a;
boolean b;
boolean c;
boolean d;
boolean e;
boolean f;
boolean g;
boolean h;

и нужна обратная операция. упаковывать boolean тегов в int.

axill
Offline
Зарегистрирован: 05.09.2011

Вы сначала скажите какую задачу хотите решить

не понимая задачи не возможно предложить верное решение

std
Offline
Зарегистрирован: 05.01.2012
Deep Sky
Offline
Зарегистрирован: 12.10.2014

такое побитовое общение нужна по I2C (Master & Slave). состояние 8 входов slave упаковывается с boolean в int и подается в master.

а в master-e распаковывается.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

А что не так с предложением от std?

axill
Offline
Зарегистрирован: 05.09.2011

Gippopotam пишет:

А что не так с предложением от std?

нормально, но есть и удобнее способ именно под задачу ТС:

union {
    struct {
        boolean a : 1;
        boolean b : 1;
        boolean c : 1;
        boolean d : 1;
        boolean e : 1;
        boolean f : 1;
        boolean g : 1;
        boolean h : 1;
    } bit;
    byte pack;
} i;

i.bit.a = 1;
i.bit.b = 2;
i.pack = 255;

А есть способ эффективнее, но менее удобнее (я предположил, что h - самый старший бит, a - младший):

i = (h << 7) | (g << 6) | (f << 5) | (e << 4) | (d << 3) | (c << 2) | (b << 1) | a;

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

sva1509
Offline
Зарегистрирован: 07.12.2012

2axill Вы предложили правильное решение. Только в битовых полях не используются типы кроме signed, unsigned. Причем 1-но битовое поле всегда unsigned. И еще 1-но битовое поле не может быть = 2.

i.bit.a=1;

i.bit.b=1;

в этом случае i.pack = 3;

axill
Offline
Зарегистрирован: 05.09.2011

2-ка это опечатка, вы правы. Откуда информация про то, что битовые поля обязаны быть только signed/unsigned? Не помню такого в спецификации

sva1509
Offline
Зарегистрирован: 07.12.2012

http://www.c-cpp.ru/books/bitovye-polya

Видел там :)

Вообще, просто нет других типов. float  не объявиш, объявлять int, long, short, char - безсмысленно, так как это одно итоже просто разного размера, а размер битового поля вы задаете сами. Вот и остается только определится, signed или unsigned.

axill
Offline
Зарегистрирован: 05.09.2011

насколько я понял в расширении С++ которое используется в ардуине нет ограничений на тип полей в битовых структурах. И почему это бессмыслено объявлять другие типы? Очень даже осмысленно. Это удобно с точки зрения читаемости кода. Но конечно это очень накладко с точки зрения ресурсов МК. Код создаваемый при использовании битовых полей существенно больше по размеру чем если ручками применять операции манипуляции с битами.

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