На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> BitField , битовые поля
    Если кому надо, класс для работы с битовыми полями:
    ExpandedWrap disabled
      template <typename T, UINT32 LSB, UINT32 MSB>
      class CBitField
      {
        enum { MASK = ((1<<(MSB - LSB + 1))-1) };
        enum { UMASK = (-1) ^ MASK << LSB };
        T m_field;
      public:
        operator T() const
        {
          return (m_field>>LSB) & MASK;
        }
        template <typename U> T operator = (U val)
        {
          m_field &= UMASK;
          m_field |= (static_cast<T>(val) & MASK) << LSB;
          return *this;
        }
      };

    Шаблонный параметр T определяет тип, в котором выделяется битовое поле.
    LSB - младший бит в поле, MSB - старший бит.

    Используется следующим образом:
    ExpandedWrap disabled
      union UToneType
      {
        CBitField<UINT16, 0, 3> energy;
        CBitField<UINT16,13,13> reuse;
        CBitField<UINT16,14,14> report;
        CBitField<UINT16,15,15> cyclic;
       
        UINT16 packet;
        UToneType(UINT16 init_value=0): packet(init_value) {}
      };


    Работа с полным пакетом осуществляется через packet.

    Предупреждение: при попытке засунуть битовое поле в функцию с шаболонным параметром, оператор T() вызывать вручную или указывать тип T непосредственно, т.к. компилятор в шаблонный параметр будет подставлять класс CBitField<....>, а не тип в битовом поле.

    Например, код:
    ExpandedWrap disabled
      template <typename T> void LOG_print(T value)
      {
        printf("%x\n",value);
      }
       
      int main()
      {
        UToneType uTone;
        uTone.packet = 0xAAAA;
       
        LOG_print(uTone.energy);
        LOG_print(static_cast<UINT16>(uTone.energy));
        LOG_print<UINT16>(uTone.energy);
        return 0;
      }

    выведет
    Цитата
    aaaa
    a
    a
      Вообще-то использовать типы вроде UINT32 - не очень хорошая мысль. Лучше заменить на unsigned. Не должен один простой отдельностоящий класс тянуть за собой другие необязательные/специфичные библиотеки/заголовочные файлы. Тем более ради всего-лишь одного-единственного примитивного определения.
        Я специально не стал приаттачивать заголовочный файл. Пусть каждый, кому это понадобится, пропишет типы, которые определены у него. В то же время, тип unsigned не есть платформонезависимый, и, при переносе проекта, скажем, с 16-разрядной платформы на 32-разрядную, могут возникнуть проблемы.
          Ага :D
          Цитата
          T m_field;
          Цитата
          return (m_field>>LSB) & MASK;
          А не сдвинуть ли мне 32-разрядную переменную на пару миллионов бит вправо? :D
            Цитата trainer @
            А не сдвинуть ли мне 32-разрядную переменную на пару миллионов бит вправо?
            Я не возражаю ;) Сдвиг у нас не циклический, поэтому и получим 0 на выходе.
            З.Ы. не для кривых рук делалось.
              Цитата Rikkie @
              Сдвиг у нас не циклический, поэтому и получим 0 на выходе.
              Не факт.
              Один компилятор/процессор может ничего не делать, а другой - сдвинуть на 1000000%32=0 бит вправо.
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0221 ]   [ 15 queries used ]   [ Generated: 30.04.24, 21:00 GMT ]