[英]How to initialize bitfields with a C++ Constructor?
First off, I'm not concerned with portability, and can safely assume that the endianness will not change. 首先,我不关心可移植性,并且可以安全地假设字节顺序不会改变。 Assuming I read a hardware register value, I would like to overlay that register value over bitfields so that I can refer to the individual fields in the register without using bit masks.
假设我读取了硬件寄存器值,我想将该寄存器值覆盖在位域上,这样我就可以参考寄存器中的各个字段而不使用位掩码。
EDIT: Fixed problems pointed out by GMan, and adjusted the code so it's clearer for future readers. 编辑:修复了GMan指出的问题,并调整了代码,以便将来读者更清楚。
SEE: Anders K. & Michael J's answers below for a more eloquent solution. 请参阅: Anders K.和Michael J的答案,以获得更有说服力的解决方案。
#include <iostream>
/// \class HardwareRegister
/// Abstracts out bitfields in a hardware register.
/// \warning This is non-portable code.
class HardwareRegister
{
public:
/// Constructor.
/// \param[in] registerValue - the value of the entire register. The
/// value will be overlayed onto the bitfields
/// defined in this class.
HardwareRegister(unsigned long registerValue = 0)
{
/// Lots of casting to get registerValue to overlay on top of the
/// bitfields
*this = *(reinterpret_cast<HardwareRegister*>(®isterValue));
}
/// Bitfields of this register.
/// The data type of this field should be the same size as the register
/// unsigned short for 16 bit register
/// unsigned long for 32 bit register.
///
/// \warning Remember endianess! Order of the following bitfields are
/// important.
/// Big Endian - Start with the most signifcant bits first.
/// Little Endian - Start with the least signifcant bits first.
unsigned long field1: 8;
unsigned long field2:16;
unsigned long field3: 8;
}; //end class Hardware
int main()
{
unsigned long registerValue = 0xFFFFFF00;
HardwareRegister testRegister(registerValue);
// Prints out for little endianess machine
// Field 1 = 0
// Field 2 = 65535
// Field 3 = 255
std::cout << "Field 1 = " << testRegister.field1 << std::endl;
std::cout << "Field 2 = " << testRegister.field2 << std::endl;
std::cout << "Field 3 = " << testRegister.field3 << std::endl;
}
Bitfields don't work that way. Bitfields无法正常工作。 You can't assign a scalar value to a
struct
full of bitfields. 您不能将标量值分配给充满位域的
struct
。 It looks like you already know this since you used reinterpret_cast
, but since reinterpret_cast
isn't guaranteed to do very much, it's just rolling the dice. 看起来你已经知道了,因为你使用了
reinterpret_cast
,但由于reinterpret_cast
不能保证做得非常多,所以它只是掷骰子。
You need to encode and decode the values if you want to translate between bitfield structs and scalars. 如果要在位域结构和标量之间进行转换,则需要对值进行编码和解码。
HW_Register(unsigned char value)
: field1( value & 3 ),
field2( value >> 2 & 3 ),
field3( value >> 4 & 7 )
{}
Edit : The reason you don't get any output is that the ASCII characters corresponding to the numbers in the fields are non-printing. 编辑 :您没有得到任何输出的原因是与字段中的数字对应的ASCII字符是非打印的。 Try this:
尝试这个:
std::cout << "Field 1 = " << (int) testRegister.field1 << std::endl;
std::cout << "Field 2 = " << (int) testRegister.field2 << std::endl;
std::cout << "Field 3 = " << (int) testRegister.field3 << std::endl;
don't do this 不要这样做
*this = *(reinterpret_cast<HW_Register*>(®isterValue));
the 'this' pointer shouldn't be fiddled with in that way: 'this'指针不应该以这种方式摆弄:
HW_Register reg(val)
HW_Register *reg = new HW_Register(val)
here 'this' is in two different places in memory 这里'这'在记忆中有两个不同的地方
instead have an internal union/struct to hold the value, that way its easy to convert back and forth (since you are not interested in portability) 相反,有一个内部联合/结构来保存值,这样很容易来回转换(因为你对可移植性不感兴趣)
eg 例如
union
{
struct {
unsigned short field1:2;
unsigned short field2:4;
unsigned short field3:2;
...
} bits;
unsigned short value;
} reg
edit: true enough with the name 'register' 编辑:足够真实,名称为'register'
Try this: 尝试这个:
class HW_Register
{
public:
HW_Register(unsigned char nRegisterValue=0)
{
Init(nRegisterValue);
}
~HW_Register(void){};
void Init(unsigned char nRegisterValue)
{
nVal = nRegisterValue;
}
unsigned Field1() { return nField1; }
unsigned Field2() { return nField2; }
unsigned Field3() { return nField3; }
private:
union
{
struct
{
unsigned char nField1:2;
unsigned char nField2:4;
unsigned char nField3:2;
};
unsigned char nVal;
};
};
int main()
{
unsigned char registerValue = 0xFF;
HW_Register testRegister(registerValue);
std::cout << "Field 1 = " << testRegister.Field1() << std::endl;
std::cout << "Field 2 = " << testRegister.Field2() << std::endl;
std::cout << "Field 3 = " << testRegister.Field3() << std::endl;
return 0;
}
HW_Register(unsigned char registerValue) : field1(0), field2(0), field3(0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.