Re[9]: & в битовом поле
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.02.08 18:51
Оценка:
Здравствуйте, Erop, Вы писали:

Pzz>>"Использовать" это оговорка? Имелось ввиду, инлайнить?

E>А что обозначает слово "инлийнить"? Вообще-то компилятор не обязан именно подставлять. Он просто может использовать для оптимизации определение функции. Есть много путей это сделать вообще-то.

Вы что сказать-то хотите?

Pzz>>Это все не так просто, на самом деле. Например, если описать функцию в ашнике, и использовать этот ашник из нескольких разных модулей, указатель на функцию будет один и тот же. Статические переменные инлайновой функции будут одни и те же. Это требует довольно нетривиальной поддержки в линкере.


E>Во-первых это таки проблемы линкера, но они невелики

E>Во-вторых что тут умного? Ну заводишь сегмент данных который называется "статическая переменная из такой-то функции" и всюду ссылаешься на него.

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

Такой интеллект в линкере появился только вместе с C++, раньше этого не было.

Кстати, ситуация становится еще интереснее, если разные части программы собирались разными компиляторами, но с одними и теми же .h-файлами, и инлайновыми функциями, в них определенными. Или, допустим, если инлайновая функция используется и в программе, и в DLL, т.е. в разных единицах компоновки. Кстати, насколько я понимаю, ни один из существующих тулчейнов не умеет разруливать такие хитрые случаи корректно.
Re[4]: & в битовом поле
От: andrey-S  
Дата: 18.02.08 08:38
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Roman Odaisky, Вы писали:


RO>>2. Битовые поля с членами знаковых типов — абсолютное зло.

E>ИМХО Гитлер всё-таки был хуже

E>Но в целом я согласен, что bitfields лучше избегать. Просто потому, что так проще.


Да вы просто не умеете их готовить...
bitfields нужны только в тех случаях, когда нужно запарсить какой-то int или short или даже char.
Например выставить какие-то флажки в регистрах аппаратуры или иногда в базе данных.

Работать с консртукцией типа:

    union UChannelMode
    {
      struct 
      {
        DWORD NofPulses           : 8;   //! (0x000000FF) бит 1 - 8 - число импульсов сигнала  (0 - простой импульс)
        DWORD ComplexSignalEnable : 1;   //! (0x00000100) бит 9 - Наличие сложного сигнала,
        DWORD LogAmlifierEnable   : 1;   //! (0x00000200) бит 10 - Логарифм. усилитель,
        DWORD AGCEnable           : 1;   //! (0x00000400) бит 11 - АРУ,
        DWORD TVGEnable           : 1;   //! (0x00000800) бит 12 - ВРЧ,
        DWORD WaveType            : 2;   //! (0x00003000) бит 13 - 14 - тип волны: LL - 0, LT - 1, TL - 2, TT - 3
        DWORD RegistrationType    : 2;   //! (0x0000C000) бит 15 - 16 - схема регистрации (совмещенная, р/с, раздельная)
        DWORD PriorityAxis        : 1;   //! (0x00010000) бит 17 - Приоритетная ось сканирования
        DWORD Skip                : 1;   //! (0x00020000) бит 18 - канал выключен
        DWORD FilterEnable        : 1;   //! (0x00040000) бит 19 - включение (1) / выключение фильтра низких частот
        DWORD DetectFilter        : 2;   //! (0x00180000) бит 20 - 21 - фильтр детектора
        DWORD AverCount           : 5;   //! (0x03E00000) бит 22 - 26 - количество усреднений
        DWORD UnitingType         : 2;   //! (0x0C000000) бит 27 - 28 - тип объединения / 0 - объединения нет
      } bit;

      DWORD dw;
      UChannelMode() : dw(0) {}
   };


намного удобнее, чем с голым int и набором масок.

E>Есть ещё один забабах -- это когда ты так как-то пишешь:
enum MyEnum { zero, one, two, three };
E>struct MyStruct { MyEnum Data : 2; };
E>MyStruct tmp = { two };

E>То фиг его знаешь чего там получишь

В bitfields все поля обязательно должны быть unsigned. Иначе могут быть бааальшие проблемы при проверках типа: mode.dw.NofPulses == 6
Re[5]: & в битовом поле
От: Erop Россия  
Дата: 18.02.08 09:05
Оценка:
Здравствуйте, andrey-S, Вы писали:

AS>Да вы просто не умеете их готовить...

AS>bitfields нужны только в тех случаях, когда нужно запарсить какой-то int или short или даже char.
AS>Например выставить какие-то флажки в регистрах аппаратуры или иногда в базе данных.

Ну это пока ты не захотел переносимости на другой компилятор...
Вообще-то я не понимаю, что мешает написать переносимое и последовательное C++ средство доступа к битовому полю...
Хотя и через bf эта проблема решается более или менее приемлемо.
Так что если у тебя это только в одном месте, то я бы может и оставил бы bf, или через маски написал бы.

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

E>>Есть ещё один забабах -- это когда ты так как-то пишешь:
enum MyEnum { zero, one, two, three };

AS>В bitfields все поля обязательно должны быть unsigned. Иначе могут быть бааальшие проблемы при проверках типа: mode.dw.NofPulses == 6
Когда речь идёт о enums, то у тебя обычно нет возможности навязать компилятору беззнаковость...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: & в битовом поле
От: elcste  
Дата: 18.02.08 10:01
Оценка:
Здравствуйте, andrey-S, Вы писали:

AS>Да вы просто не умеете их готовить...

AS>bitfields нужны только в тех случаях, когда нужно запарсить какой-то int или short или даже char.
AS>Например выставить какие-то флажки в регистрах аппаратуры или иногда в базе данных.

Да, это все правда. Но только при двух условиях:

1) переносимость не нужна;
2) скорость не интересует.
Re[6]: & в битовом поле
От: andrey-S  
Дата: 18.02.08 12:19
Оценка:
Здравствуйте, Erop, Вы писали:

AS>>bitfields нужны только в тех случаях, когда нужно запарсить какой-то int или short или даже char.

AS>>Например выставить какие-то флажки в регистрах аппаратуры или иногда в базе данных.

E>Ну это пока ты не захотел переносимости на другой компилятор...


Если разрядность процессора не меняется, то никакой непереносимости вроде нет. Да и тогда эта проблема разрешима.
Формат получается одинаковый и в С, и в С++ в MSVC, Builder-6 и в мVision.
Под другим компилятором наверное понимается другой язык программирования? Или я чего-то не понял.


E>Вообще-то я не понимаю, что мешает написать переносимое и последовательное C++ средство доступа к битовому полю...

E>Хотя и через bf эта проблема решается более или менее приемлемо.
E>Так что если у тебя это только в одном месте, то я бы может и оставил бы bf, или через маски написал бы.
E>Если местах в пяти, то я бы, конечно написал какой-нибудь способ порождать геттеры и сеттеры.

Как правило работа с аппаратурой реализуется в одном проекте и компилится одним компилятором.
В этом случае битовое поле довольно удобное средство поскольку:
1) для создания и поддержки разных форматов требуется гораздо меньше усилий
(например написание и поддержка методов get и set например для 20-40 разных форматов — довольно трудоёмко)
2) нельзя по ошибке выставить "левый" разряд в битовом поле перепутав его название,
чего не скажешь про маски. Они работают по принципу все со всеми.
3) часто запись с использованием битового поля короче и нагляднее чем через маски:


enum {
  MASK_dat1 = 0x02F0
};

struct BF
{
  unsigned dat0 : 4;
  unsigned dat1 : 6;
};

unsigned reg0;
BF reg1;

void setReg(unsigned d1)
{
  reg0 = (~reg0 & MASK_dat1) & (d1 << 4); //вариант работы через маски
  reg1.dat1 = d1;    // вариант с bitfields
}


Впрочем я предпочитаю комбинацию bitfield и масок:
bitfield — если надо установить одно поле,
маска — если надо установить сразу несколько полей, а форматы уже утряслись

Если требуется платформонезависимый экспорт, можно создать это средство.
Но в реализации его также часто удобно использовать bitfields.


E>>>Есть ещё один забабах -- это когда ты так как-то пишешь:
enum MyEnum { zero, one, two, three };

AS>>В bitfields все поля обязательно должны быть unsigned. Иначе могут быть бааальшие проблемы при проверках типа: mode.dw.NofPulses == 6
E>Когда речь идёт о enums, то у тебя обычно нет возможности навязать компилятору беззнаковость...

Потому надо взять за правило: не использовать enum в bitfields.
Re[7]: & в битовом поле
От: andrey-S  
Дата: 19.02.08 07:52
Оценка:
Здравствуйте, andrey-S, Вы писали:

Простите! Написал глупость.
Правильно:

void setReg(unsigned d1)
{
  reg0 = (reg0 & ~MASK_dat1) | ((d1 << 4) & MASK_dat1); //вариант работы через маски
  reg1.dat1 = d1;    // вариант с bitfields
}
Re[6]: & в битовом поле
От: andrey-S  
Дата: 19.02.08 07:53
Оценка:
Здравствуйте, elcste, Вы писали:

AS>>Да вы просто не умеете их готовить...

AS>>bitfields нужны только в тех случаях, когда нужно запарсить какой-то int или short или даже char.
AS>>Например выставить какие-то флажки в регистрах аппаратуры или иногда в базе данных.

E>Да, это все правда. Но только при двух условиях:


E>1) переносимость не нужна;

E>2) скорость не интересует.

Про скорость не понял . Можете пояснить?
Re[7]: & в битовом поле
От: elcste  
Дата: 19.02.08 08:50
Оценка:
Здравствуйте, andrey-S, Вы писали:

E>>2) скорость не интересует.


AS>Про скорость не понял . Можете пояснить?


Попробуйте написать разбор/создание какого-нибудь битстрима на bit-fields и посмотрите, какой код Вам сгенерировал Ваш компилятор.

P.S. Да, я понимаю, что аппаратура может быть и с битовой адресацией, но исходить приходится из того, с чем сталкиваешься в действительности.
Re[8]: & в битовом поле
От: andrey-S  
Дата: 19.02.08 09:19
Оценка:
Здравствуйте, elcste, Вы писали:

E>>>2) скорость не интересует.

AS>>Про скорость не понял . Можете пояснить?

E>Попробуйте написать разбор/создание какого-нибудь битстрима на bit-fields и посмотрите, какой код Вам сгенерировал Ваш компилятор.


Согласен . В обычной практики для экономии места использовать bit-fields не стоит.
Я лишь хочу отметить, что bit-fields довольно удобны, если надо запарсить или распарсить какой-нибудь int.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.