& в битовом поле
От: k55 Ниоткуда  
Дата: 14.02.08 07:40
Оценка:
Подскажите где посмотреть вот про этот запрет (или объясните чем он обусловлен):

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

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


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

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

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

Мля.

Горе от ума.
Спасибо.
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
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[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[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]: & в битовом поле
От: 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[4]: & в битовом поле
От: Roman Odaisky Украина  
Дата: 15.02.08 15:49
Оценка: +1
Здравствуйте, Pzz, Вы писали:

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


За что так сразу. inline — это стандартный аналог того, что MS называет __declspec(selectany), и это очень важно.
До последнего не верил в пирамиду Лебедева.
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, а взял любое из определений.
Ну и на само тело функции тоже.

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