Re[2]: & в битовом поле
От: Roman Odaisky Украина  
Дата: 14.02.08 19:33
Оценка: 6 (1) +1 :)
Здравствуйте, Erop, Вы писали:

k55>>error C2104 "'&' в битовом поле".

k55>> Была сделана попытка взять адрес битового поля.

E>В стандарте, там где bitfields jписаны...


E>Общая идея такая, что когда ты используешь bitfields, например так:
struct MyBitFields {
E>    int Data1 : 7;
E>    int Data2 : 12;
E>    int Data3 : 13;
E>};

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

Битовые поля — вообще чудаческие вещи.

Например, struct Test { signed int x : 1; }. Какие значения может принимать Test::x? Правильно, 0 и -1. test.x = 1 — переполнение.

Всё даже еще хуже. struct Test { int x : 1; } test = { 1 } может быть и well-formed. Потому что во всех остальных местах int = signed int, но только не в битовых полях! Там это просто не определено (9.6/3), так что int без указания знаковости может быть и unsigned.

Вообще,

1. Битовые поля — зло;
2. Битовые поля с членами знаковых типов — абсолютное зло. :-)
До последнего не верил в пирамиду Лебедева.
Re: & в битовом поле
От: valker  
Дата: 14.02.08 07:56
Оценка: +2
Здравствуйте, k55, Вы писали:

k55>Подскажите где посмотреть вот про этот запрет (или объясните чем он обусловлен):


k55>error C2104 "'&' в битовом поле".

k55> Была сделана попытка взять адрес битового поля.

Думаю, потому что минимально адресуемым является байт, а не бит...
Re[6]: & в битовом поле
От: k55 Ниоткуда  
Дата: 14.02.08 12:30
Оценка: :))
Здравствуйте, Erop, Вы писали:
E>Ну у тебя же и так там объединение из структуры из двух байт и одного двубайта?
E>Зачем туда ещё и bitfields прихреначивать?

Мля.

Горе от ума.
Спасибо.
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re: & в битовом поле
От: Erop Россия  
Дата: 14.02.08 08:15
Оценка: 2 (1)
Здравствуйте, k55, Вы писали:

k55>error C2104 "'&' в битовом поле".

k55> Была сделана попытка взять адрес битового поля.

В стандарте, там где bitfields jписаны...

Общая идея такая, что когда ты используешь bitfields, например так:
struct MyBitFields {
    int Data1 : 7;
    int Data2 : 12;
    int Data3 : 13;
};

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

Соответсвенно компилятор заведёт в вышеприведённом примере (это от реализации вообще-то зависит, но так в популярных тут компиляторах будет) ОДНО поле типа int и будет в нём всякими операциями с битами доставать и устанавливать куски.

То есть он, реально родит что-то вроде такого класса (это не реальный код, а просто изложение идеии на языке С++. С формальной точкип зрения тут есть много тонкостей, учёт которых загромоздит объяснение):
class MyBitFieldsImpl {
public:

    void SetData1( int value ) { setField( Data1_mask, Data1_offset, value ); }
    int GetData1() const { return getField( Data1_mask, Data1_offset ); }
    
    void SetData2( int value ) { setField( Data2_mask, Data2_offset, value ); }
    int GetData2() const { return getField( Data2_mask, Data2_offset ); }
    
    void SetData3( int value ) { setField( Data3_mask, Data3_offset, value ); }
    int GetData3() const { return getField( Data3_mask, Data3_offset ); }
    
private:
    enum { Data1_offset = 0, Data1_mask = 127 };
    enum { Data2_offset = 7, Data2_mask = (1 << 20) - 1 - Data1_mask };
    enum { Data3_offset = 19, Data3_mask = 0xFFFFFFFF - Data2_mask };
    
    int data;

    void setField( int mask, int offset, int value )
    {
        data = ( data & ~mask ) | ( mask & ( value << offset ) );
    }
    int getField( int mask, int offset ) const 
    {
        return ( data >> offset ) & mask;
    }
}

И когда ты пишешь
int foo()
{
    MyBitFields tmp;
    tmp.Data1 = 5;
    tmp.Data2 = -7;
    tmp.Data3 = tmp.Data1 + tmp.Data2;
    return tmp.Data3;
}


То компилятор генерирует код эквивалентный следующему:
int foo()
{   MyBitFieldsImpl tmp;
    tmp.SetData1( 5 );
    tmp.SetData2( -7 );
    tmpSetData3( tmp.GetData1() + tmp.GetData2() );
    return tmp.GetData3();
}


В результате ты получаешь более компактные данные, но платишь за это менее эффективной работой с ними. Кроме того у тебя возникает ряд ограничений, одно из которых -- отсутсвие адреса у bitfield.
B действительно, просто в памяти компьютера физически нет такого int, в котором хранится поле MyFields::Data2, например. Так что и адреса у него нет.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: & в битовом поле
От: Erop Россия  
Дата: 14.02.08 11:33
Оценка: 2 (1)
Здравствуйте, k55, Вы писали:

k55>Ну и в ответ первому устройству нужно состовную команду из байтов высылать.

k55>Посчитал что так удобнее будет.

Ну у тебя же и так там объединение из структуры из двух байт и одного двубайта?
Зачем туда ещё и bitfields прихреначивать?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: & в битовом поле
От: AleksandrN Россия  
Дата: 14.02.08 11:46
Оценка: +1
Здравствуйте, k55, Вы писали:

k55>От устройства идет команда в два байта, а точнее шорт.

k55>Программа парсит эту команду и в соотвествии с протоколом выдает другому устройству нечто другое.
k55>Так вот, чтобы распарсить нужно обращаться к каждому байту.

union a {
    short cmd;
    byte bytes[2];
};
Re[3]: & в битовом поле
От: elcste  
Дата: 15.02.08 06:51
Оценка: +1
Здравствуйте, Roman Odaisky, Вы писали:

RO>Всё даже еще хуже. struct Test { int x : 1; } test = { 1 } может быть и well-formed.


Не придирки ради, но только точности для. Well-formed оно-то в любом случае будет (ну, про точку с запятой все понятно, да). Вот значение и в самом деле может быть implementation-defined.
Re[4]: & в битовом поле
От: Roman Odaisky Украина  
Дата: 15.02.08 15:49
Оценка: +1
Здравствуйте, Pzz, Вы писали:

Pzz>P.S. А вот адрес inline функции брать можно — такой у нас уродский язык :-)


За что так сразу. inline — это стандартный аналог того, что MS называет __declspec(selectany), и это очень важно.
До последнего не верил в пирамиду Лебедева.
& в битовом поле
От: k55 Ниоткуда  
Дата: 14.02.08 07:40
Оценка:
Подскажите где посмотреть вот про этот запрет (или объясните чем он обусловлен):

error C2104 "'&' в битовом поле".
Была сделана попытка взять адрес битового поля.
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re[2]: & в битовом поле
От: k55 Ниоткуда  
Дата: 14.02.08 08:01
Оценка:
Здравствуйте, valker, Вы писали:

V>Здравствуйте, k55, Вы писали:


k55>>Подскажите где посмотреть вот про этот запрет (или объясните чем он обусловлен):


k55>>error C2104 "'&' в битовом поле".

k55>> Была сделана попытка взять адрес битового поля.

V>Думаю, потому что минимально адресуемым является байт, а не бит...


Даже если у меня структура вида:


    union TPairByte {
        struct  {
            byte m_FirstByte : 8;
            byte m_SecondByte : 8;
        };
        short m_CommandShort;
    };


Т.е. компилятор не парится с разбором?
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re[3]: & в битовом поле
От: Erop Россия  
Дата: 14.02.08 09:54
Оценка:
Здравствуйте, k55, Вы писали:

k55>
k55>    union TPairByte {
k55>        struct  {
k55>            byte m_FirstByte : 8;
k55>            byte m_SecondByte : 8;
k55>        };
k55>        short m_CommandShort;
k55>    };
k55>


А смысл?

k55>Т.е. компилятор не парится с разбором?

А никто не обещал, что он по граница байт будет на всех платформах ранить...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: & в битовом поле
От: k55 Ниоткуда  
Дата: 14.02.08 11:21
Оценка:
Здравствуйте, Erop, Вы писали:

E>А смысл?


Может не верное решение.

От устройства идет команда в два байта, а точнее шорт.
Программа парсит эту команду и в соотвествии с протоколом выдает другому устройству нечто другое.
Так вот, чтобы распарсить нужно обращаться к каждому байту.

Ну и в ответ первому устройству нужно состовную команду из байтов высылать.
Посчитал что так удобнее будет.
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re[3]: & в битовом поле
От: Erop Россия  
Дата: 14.02.08 19:40
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

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

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

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

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

То фиг его знаешь чего там получишь
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: & в битовом поле
От: Pzz Россия https://github.com/alexpevzner
Дата: 14.02.08 21:48
Оценка:
Здравствуйте, k55, Вы писали:

k55>Даже если у меня структура вида:

k55>
k55>    union TPairByte {
k55>        struct  {
k55>            byte m_FirstByte : 8;
k55>            byte m_SecondByte : 8;
k55>        };
k55>        short m_CommandShort;
k55>    };
k55>

k55>Т.е. компилятор не парится с разбором?

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

P.S. А вот адрес inline функции брать можно — такой у нас уродский язык
Re[4]: & в битовом поле
От: elcste  
Дата: 15.02.08 07:01
Оценка:
Здравствуйте, Erop, Вы писали:

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

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

two, разумеется (9.6/4).

А ошибки, конечно, в компиляторах самые неожиданные встречаются, если Вы об этом.
Re[5]: & в битовом поле
От: Cyberax Марс  
Дата: 15.02.08 15:55
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

Pzz>>P.S. А вот адрес inline функции брать можно — такой у нас уродский язык

RO>За что так сразу. inline — это стандартный аналог того, что MS называет __declspec(selectany), и это очень важно.
Вообще говоря, нет. __declspec(any) применяется к переменным, inline к ним неприменим.
Sapienti sat!
Re[5]: & в битовом поле
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.02.08 16:24
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

Pzz>>P.S. А вот адрес inline функции брать можно — такой у нас уродский язык


RO>За что так сразу. inline — это стандартный аналог того, что MS называет __declspec(selectany), и это очень важно.


Я не знаю, чего мелкософт называет этим страшным словом. Но inline — это намек компилятору о том, что функцию хорошо бы поинлаинить. А register — намек компилятору о том, что переменную хорошо бы положить в регистр. Очевидно, что если функцию удалось поинлайнить, и переменную удалось положить в регистр, у них нет адреса. При этом адрес инлайновой функции получить можно (компилятору, естественно, придется ради этого сгенерировать нормальную, не инлайновую функцию), а адрес регистровой переменной получить нельзя. Получается неконсистентность.
Re[6]: & в битовом поле
От: Erop Россия  
Дата: 15.02.08 16:59
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Но inline — это намек компилятору о том, что функцию хорошо бы поинлаинить.


В действительности современные компиляторы пробуют использовать все доступные в точке вызова определения функций. И inline и не inline. Но ключевое слово inline позволяет опубликовать определение функции для нескольких едениц трансляции, не нарушая ODR.

При этом указатель на inline функцию ничем не хуже указателя на не-inline функцию.
Ты же не можешь с указателем на функцию сдлеать ничего, кроме как сравнить два, или вызывать ненулевой. К тому подставился код функции в каком-то другом месте или нет это не имеет никакого отношения...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: & в битовом поле
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.02.08 17:12
Оценка:
Здравствуйте, Erop, Вы писали:

E>В действительности современные компиляторы пробуют использовать все доступные в точке вызова определения функций. И inline и не inline. Но ключевое слово inline позволяет опубликовать определение функции для нескольких едениц трансляции, не нарушая ODR.


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

Современные компиляторы хоть и умеют автоматически инлайнить, обычно они все же воспринимают намеки. Скажем, явное описание inline может привести к тому, что поинлайнится функция, которую иначе бы компилятор инлайнить не стал.

E>При этом указатель на inline функцию ничем не хуже указателя на не-inline функцию.

E>Ты же не можешь с указателем на функцию сдлеать ничего, кроме как сравнить два, или вызывать ненулевой. К тому подставился код функции в каком-то другом месте или нет это не имеет никакого отношения...

Это все не так просто, на самом деле. Например, если описать функцию в ашнике, и использовать этот ашник из нескольких разных модулей, указатель на функцию будет один и тот же. Статические переменные инлайновой функции будут одни и те же. Это требует довольно нетривиальной поддержки в линкере.
Re[8]: & в битовом поле
От: Erop Россия  
Дата: 15.02.08 18:30
Оценка:
Здравствуйте, Pzz, Вы писали:

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

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

Pzz>Современные компиляторы хоть и умеют автоматически инлайнить, обычно они все же воспринимают намеки. Скажем, явное описание inline может привести к тому, что поинлайнится функция, которую иначе бы компилятор инлайнить не стал.


Ну обычно у них есть ещё всякие другие слова для намёков. А вот собственно inline примерно так же учитывают, как register...

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


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

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

И что за проблема?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
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...
Пока на собственное сообщение не было ответов, его можно удалить.