Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Операции с битами (перевод байта в бит)

Вт окт 02, 2012 22:55:58

Добрый вечер уважаемые форумчане.

У меня такой вопрос:

Имею байтовые переменные

unsigned char x, y, z, k, l;

но я реально пользую 1бит каждого байта как флаги.

Как можно через дефайны или еще как то перевести байты в биты для экономии памяти?

Что то либо уже голова не соображает, либо это сложная задача :)

Такие и наподобии таких вариантов не предлагать так как много кода переписывать :((

if ((x & 0x01)==0) { /* что то делаем */ }

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:03:24

У i51 есть битовые переменные

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:08:00

Я знаю, есть

bit x;

Но мне надо аналог сделать без применения bit

Все из за того что когда то столкнулся с проблемой что компилятор гад выкинул при оптимизации важные участки кода где использовался бит и я долго не мог понять в чем проблема....

а так выдает ошибку....

volatile bit x;

то есть получается нельзя указать что бит является важным и выкидывать задержки и команды нельзя.... :(

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:13:26

Код:
struct Flag_Collection
{
   unsigned flag1  : 1;    // 0   
   unsigned flag2  : 1;    // 1 
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
};
// ....
strust Flag_Collection flagi;
// ...
flagi.flag1=0;
flagi.flag7=1;


Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:25:05

Не работает... :(

Вот я так как то и хочу, но такой вариант не работает..

Так у меня есть:

Код:
#define  x (data_bit & 0x01)

unsigned char data_bit;

if(key)
{
if (x==1) x=0;
else x=1;
}

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:29:29

Tolmi писал(а):
Код:
struct Flag_Collection
{
   unsigned flag1  : 1;    // 0   
   unsigned flag2  : 1;    // 1 
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
};
// ....
strust Flag_Collection flagi;
// ...
flagi.flag1=0;
flagi.flag7=1;




Ваш код тоже не подходит :(

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:35:54

pre-scriptum: Пока я отвлекался, фактически то же самое уже было написано, но я и свои 5 копеек вставляю.

Ваш код тоже не подходит :(

Ну и вопрос сразу: странно — какой это компилятор не поддерживает битовые поля?
Они существуют с давних пор, от начала существования С.

Artos писал(а):Имею байтовые переменные
unsigned char x, y, z, k, l;
Для начала, если это не «так, для примера», а реальные переменные, очень рекомендую перестать использовать однобуквенные имена для чего-либо, кроме «очень локальных» переменных, например, индексов циклов. Т.е. от места определения такой переменной до места её исчезновения должно быть не больше половины экрана кода :-)
Иначе очень быстро с ростом размеров программ будет путаница.
А осмысленные имена избавляют от необходимости писать комментарии вида
Код:
    unsigned char b; /* это счётчик битов */ 
или
Код:
    r = 1; /* переходим в приёма */ 

В записях
Код:
    unsigned char bit_cnt; 
или
Код:
    receive_mode = 1; 
символов набирать нужно меньше :)

По флагам.
За исключением расширения языка С в виде поддержки битовых переменных, как это есть для MCS51, остальные способы разменивают размер ОЗУ на размер флеша.
Запись
Код:
enum { flag1 = 0x01, flag2 = 0x02, flag3 = 0x03 }; // Имена для примера  :))) 
uint8_t flags;

if (flags & flag1) flags &= ~flag2; 
муторная, но в большинстве компиляторов даст минимальный код. Больше, чем
Код:
if (flag1) flag2 = 0; 
но минимально возможный для упакованніх в байт битов.

Запись в виде битовых полей
Код:
struct {
    unsigned char flag1 : 1; // выделяем под поле один бит
    unsigned char flag2 : 1; // выделяем под поле один бит
    unsigned char flag3 : 1; // выделяем под поле один бит
    unsigned char       : 1; // пропускаем один бит (ровняем state на полубайт), имя не обязательно
    unsigned char state : 4; // выделяем под поле четыре бита
} fags; // в сумме 8 бит займут один байт

   if (flags.flag1) flags.state = 3; 
приятнее, но может привести к размеру кода большему, чем с масками выше. Зависит от компилятора.
Но чем ближе светлое будущее, тем компиляторы умнее, так что постепенно это становится не таким страшным.

Для возможности поиграться между расходом ОЗУ и ПЗУ я иногда делаю так
Код:
#ifdef SMALL_RAM
#define ONEBIT : 1 // будут выделены биты
#else
#define ONEBIT  // будут выделены байты
#endif

struct {
    unsigned char flag1 ONEBIT ;
    unsigned char flag2 ONEBIT ;
    unsigned char flag3 ONEBIT ;
}
 fags; 

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:38:24

Artos писал(а):volatile bit x;
У битовых полей с volatile всё в порядке, но нужно помнить, что запись даже однобитового поля для чуть менее, чем всех процессоров будет неатомарной операцией и её надо заворачивать в запрет/разрешение прерываний.

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:42:34

avreal писал(а):Для начала, если это не «так, для примера»,


Это для примера :)

У меня компилятор CVAVR

такая конструкция не пашет...

Код:
struct Flag_Collection
{
   unsigned flags_pass  : 1;    // 0   
   unsigned flag2  : 1;    // 1 
   unsigned flag3  : 1;    // 2
//.....  и так далее ...
   unsigned flag8   : 1;    // 7
} flags;

if (flags_pass ) flags_pass = 0;
else flags_pass =1;

Выдает ошибку:

Error: J:\ (1670): undefined symbol 'flags_pass'

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:46:50

avreal писал(а):Запись в виде битовых полей
Код:
struct {
unsigned char flag1 : 1; // выделяем под поле один бит
unsigned char flag2 : 1; // выделяем под поле один бит
unsigned char flag3 : 1; // выделяем под поле один бит
unsigned char : 1; // пропускаем один бит (ровняем state на полубайт), имя не обязательно
unsigned char state : 4; // выделяем под поле четыре бита
} fags; // в сумме 8 бит займут один байт

if (flags.flag1) flags.state = 3;
приятнее, но может привести к размеру кода большему, чем с масками выше. Зависит от компилятора.
Но чем ближе светлое будущее, тем компиляторы умнее, так что постепенно это становится не таким страшным.


Не подходит.... :(

Много переписывать...

Тогда мне уже будет лучше так писать:

if (bit & 0x01) bit &=~0x01;
else bit |=0x01;

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:49:42

странно .... в старых версиях CVAVR

такое не работало:

volatile bit x;

:shock:

в 2.05 уже работает.

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:52:48

Artos писал(а):Ваш код тоже не подходит :(

И чем не подходит мой код?
Спойлер
Код:
#include <stdio.h>
#include <stdlib.h>
union Flag_Union {
   unsigned char chr;
   struct bite {
      unsigned flag0:1;
      unsigned flag1:1;
      unsigned flag2:1;
      unsigned flag3:1;
      unsigned flag4:1;
      unsigned flag5:1;
      unsigned flag6:1;
      unsigned flag7:1;
   } flag;
};
union Flag_Union flagi;
int main(void) {
   flagi.chr=0; // Clear all flags
   flagi.flag.flag0=1;
   flagi.flag.flag5=1;
   if (flagi.flag.flag5==1 && flagi.flag.flag6==0){
      printf("byte=%d, flags=%d,%d,%d,%d,%d,%d,%d,%d",
            flagi.chr,
            flagi.flag.flag0,flagi.flag.flag1,flagi.flag.flag2,flagi.flag.flag3,
            flagi.flag.flag4,flagi.flag.flag5,flagi.flag.flag6,flagi.flag.flag7);
   }
   return 0;
}


Вывод:
byte=33, flags=1,0,0,0,0,1,0,0


flagi.flag.flagX можно через #define переопределить в x,y,z чтобы не тарабанить по клавиатуре каждый раз.

Re: Операции с битами (перевод байта в бит)

Вт окт 02, 2012 23:56:20

Tolmi писал(а):flagi.flag.flagX можно через #define переопределить в x,y,z чтобы не тарабанить по клавиатуре каждый раз.



Точно!
Продефайнить все имена! Тогда работать будет :)
Спасибо за подсказку!
А как обьявить битовое поле с числом битов 32шт. и более?

наверное unsigned long chr {} ?

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 00:20:46

Artos писал(а):А как обьявить битовое поле с числом битов 32шт. и более?

наверное unsigned long chr {} ?

А компилятор сам разберется, пока в структуре есть последовательно расположенные битовые поля, он будет их последовательно складывать.
будет
unsigned nameXXX:1;
повторяться 32 раза,
будет 32-битная структура.

И да, длина поля может быть больше одного бита,
например
//
unsigned pack4bit:4;
// сможет принимать
значения от 0 до 15 и занимать 4 бита.

Работает вполне предсказуемо : получение значения - сдвиг и маскирование, присвоение - сдвиг и маскирование аргументом.
Но, да, если больше жаль флэш памяти, чем оперативки, то лучше забить и использовать байтовые переменные. Просто обычно купить более ёмкую флэш память гораздо проще, чем найти процессор с большим объемом ОЗУ.

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 07:20:36

Спасибо за развернутый ответ :)

Ну оперативки тоже жалко :)
Поэтому все же лучше пожертвовать флэшой.

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 08:04:04

Здравствуйте!
Я думаю вполне можно попробовать заюзать такое:
Код:
#define   SetBit(reg, bit)          reg |= (1<<bit)           
#define   ClearBit(reg, bit)       reg &= (~(1<<bit))
#define   InvBit(reg, bit)          reg ^= (1<<bit)
#define   BitIsSet(reg, bit)       ((reg & (1<<bit)) != 0)
#define   BitIsClear(reg, bit)    ((reg & (1<<bit)) == 0)

пример использования:

Код:

SetBit(PORTB, 0);    //установить нулевой бит порта B   
InvBit(tmp,6);         //инвертировать шестой бит переменной tmp


if  (BitIsClear(PIND, 0)) {   //если очищен нулевой бит в регистре PIND                                     
…..                                     //выполнить блок
}

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 10:03:36

Хороший код! Спасибо! Взял на заметку :)

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 12:25:15

metan писал(а):Здравствуйте!
Я думаю вполне можно попробовать заюзать такое:

И код, который при этом получается, ну просто один в один такой же, как при использовании структур с битовыми полями :tea:
Тут больше вопрос привычки, я с битовыми полями работал ещё 25 лет назад на СМ-4 ;)
Сейчас любой МК мощнее её :)

Re: Операции с битами (перевод байта в бит)

Ср окт 03, 2012 17:57:40

А я вовсе самоучка . Да и занимаюсь только третий год программированием, правда интенсивно.
То например ни разу не применял битовые поля...

Как по мне красивее смотрится битовое поле. Его легче читать.
Ответить