Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Битовые поля передача по аргументу


Автор: null56 6.5.2009, 11:29
Я не совсем представляю, что из себя предсталяют битовые поля после компиляции и на сколько быстро идет к ним обращение по сравнению с отедельно взятой переменной, но я их использую, как флаги
Код

struct TBitMap
{
    unsigned char m_Bit : 1;
   // и т.д.
};

Собственно хотел спросить, возможен ли такой вариант
есть функция, которая принимает битовое поле и имеет возможность изменить его внутри тела?
надеюсь вопрос понятен... приведу пример кода, который может сделает вопрос более конкретным
Код

TBitMap MyBitMap;

void changeBitField(unsigned char & /** собственно битовое поле*/)
{
     /* битовое поле*/ = 1;
}

// вызов
changeBitField(MyBitMap.m_Bit);

Если не сложно, дополните вопрос с пояснением.... потому что для меня битовые поля - это максимально упакованные значения, как с ними работает компилятор, я уже говорил, не представляю...
Заранее благодарен за помощь

Автор: zim22 6.5.2009, 11:52
Цитата(null56 @  6.5.2009,  11:29 Найти цитируемый пост)
unsigned char m_Bit : 1;

я думал, должен быть тип unsigned int

Код

typedef unsigned int Bit;
class File {
public:
  void write() {
    modified = 1;
  }
private:
  Bit mode: 2;
  Bit modified: 1;
  Bit prot_owner: 3;
  Bit prot_group: 3;
  Bit prot_world: 3;
};

Для манипулирования битовыми полями с несколькими битами обычно используют встроенные побитовые операторы
Код

enum {READ = 01, WRITE = 02}; // режимы файла
int main() {
  File myFile;
  myFile.mode |= READ; // установить бит READ
  if (myFile.mode & READ); // если бит READ установлен
}


Классы, в которых определены битовые поля обычно снабжены и встраиваемыми методами, облегчающие установку и проверку значений битовых полей.
Например класс File мог содержать такие функции:
Код

inline int File::isRead() { return mode & READ; }
inline int File::isWrite() { return mode & WRITE; }

if (myFile.isRead());

Автор: math64 6.5.2009, 11:53
Получить ссылку на битовое нельзя. Можно разве что так:
Код

struct TBitmap {
   unsigned char bit1 : 1;
   unsigned char bit2 : 1;
   unsigned char bit3 : 1;
   unsigned char bit4 : 1;
   void SetBit(int bit, int value);
   int GetBit(int bit);
};
void TBitmap::SetBit(int bit, int value) {
   switch(bit) {
      case 1:  bit1 = value; break;
      case 2:  bit2 = value; break;
      case 3:  bit3 = value; break;
      case 4:  bit4 = value; break;
   }
}

int TBitmap::GetBit(int bit) {
   switch(bit) {
      case 1:  return bit1;
      case 2:  return bit2;
      case 3:  return bit3;
      case 4:  return bit4;
   }
}


Автор: xvr 6.5.2009, 11:55
Цитата(null56 @ 6.5.2009,  11:29)
Я не совсем представляю, что из себя предсталяют битовые поля после компиляции и на сколько быстро идет к ним обращение по сравнению с отедельно взятой переменной,

Медленнее
Цитата

Собственно хотел спросить, возможен ли такой вариант
есть функция, которая принимает битовое поле
Невозможен. Битовое поле не существует вне струкутры, где описанно. И указатель на него взять нельзя (а значит и передать по референсу)

Цитата

Если не сложно, дополните вопрос с пояснением.... потому что для меня битовые поля - это максимально упакованные значения, как с ними работает компилятор, я уже говорил, не представляю...
Ну как то так:
Код

struct BitTest {
 int bf1: 1;
 int bf2: 1;
} tst;
/* Real structure will be
struct BitTest {
 int all_bf;
} rtst;
*/
tst.bf1=1; // real op: rtst.all_bf|=1;
tst.bf1=0; // real op: rtst.all_bf&=~1;
tst.bf2=1; // real op: rtst.all_bf|=2;
tst.bf2=0; // real op: rtst.all_bf&=~2;
if (tst.bf2) // real op: if (rtst.all_bf&2)


Автор: math64 6.5.2009, 12:00
Вместо битовых полей можно использовать маски:
Код

enum Bit { bit1, bit2, bit3, bit4 };
inline bool TestBit(int&mask, Bit bit) { return mask & (1 << bit) ? true : false; }
inline SetBit(int&mask, Bit bit) { mask |= (1 << bit); }
inline ClrBit(int&mask, Bit bit) { mask &= ~(1 << bit); }
inline XorBit(int&mask, Bit bit) { mask ^= (1 << bit); }
inline SetBit(int&mask, Bit bit, bool value) { if (value) SetBit(mask, bit); else ClrBit(mask, bit); }

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

Автор: null56 6.5.2009, 12:18
Значит попробую сделать выводы.
В С++ битовое поле призвано повысить уровень абстракции, чтобы пользователю самому не приходилось реализовывать битовые операции, но компилятор в исходном машинном коде все равно будет делать тоже самое, что и делал бы пользователь, а именно те же сбросы или выставлаения битов
Сама структура с битовыми полями является байтом или более широким словом и по сути к ней можно обращаться и передавать как одну переменную и работать с ней используя битовые операции для изменения значений отдельных битов, это будет аналогично использованию возможностей компилятора по обращению к отдельным битовым полям...

Если я все верно понял, то отлично...
Все спасибо за подробные ответы

Автор: zim22 6.5.2009, 12:28
Цитата(null56 @  6.5.2009,  12:18 Найти цитируемый пост)
В С++ битовое поле призвано повысить уровень абстракции, чтобы пользователю самому не приходилось реализовывать битовые операции

уровень абстракции повысит класс из #include <bitset>

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

Автор: null56 6.5.2009, 12:47
Цитата(zim22 @ 6.5.2009,  12:28)
Битовые поля обычно используют в случае, когда программа должна передать бинарные данные другой программе или аппаратному устройству.
Расположение в памяти битовых полей является машинно-зависимым.

вот это верно подмечено.... по моему, проще потратить 9 байт на флаги, чем связываться с битовыми полями в моем случае... было бы их штук 30, тогда другой вопрос... хотя даже не знаю....
Вопрос такой, если мы объявляем структуру битового поля, то уже не имеем возможности обращаться к полям через собсвтенные битовые операции, только средствами компилятора?
подробнее на коде... так делать никак нельзя?
Код

struct BitField
{
   unsigned char bit_1 : 1;
   unsigned char bit_2 : 1;
};

BitField bf;
bd |= 1; // НИЗЯ НИКАК? чтобы выставить первый бит

Автор: zim22 6.5.2009, 12:52
Код

bf.bit_1 |= 1; // ВОТ ТАК МОЖНО! чтобы выставить первый бит

и так можно:
Код

BitField bf2 = {1, 1}; // bit_1 = 1, bit2 = 1;

Автор: math64 6.5.2009, 13:10
Код

struct BitField {
   union {
     struct {
       unsigned char bit_1 : 1;
       unsigned char bit_2 : 1;
     } bits;
     unsigned char mask;
   } u;
};

BitField bf;
bf.u.mask = 1;
bf.u.bits.bit_2 = bf.u.bits.bit_1;


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