如何使用 C++ 初始化位域构造函数?
首先,我不关心可移植性,并且可以放心地假设字节序不会改变。假设我读取硬件寄存器值,我想将该寄存器值覆盖在位字段上,以便我可以在不使用位掩码的情况下引用寄存器中的各个字段。
编辑:修复了 GMan 指出的问题,并调整了代码,以便将来的读者更清楚。
参见: 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;
}
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.
SEE: Anders K. & Michael J's answers below for a more eloquent solution.
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
位域不是这样工作的。您无法将标量值分配给充满位域的
struct
。看起来您自从使用reinterpret_cast
以来就已经知道这一点,但由于reinterpret_cast
不能保证做很多事情,所以它只是掷骰子。如果要在位域结构和标量之间进行转换,则需要对值进行编码和解码。
编辑:您没有得到任何输出的原因是与字段中的数字对应的 ASCII 字符是不可打印的。试试这个:
Bitfields don't work that way. You can't assign a scalar value to a
struct
full of bitfields. It looks like you already know this since you usedreinterpret_cast
, but sincereinterpret_cast
isn't guaranteed to do very much, it's just rolling the dice.You need to encode and decode the values if you want to translate between bitfield structs and scalars.
Edit: The reason you don't get any output is that the ASCII characters corresponding to the numbers in the fields are non-printing. Try this:
不要这样做,
“this”指针不应该以这种方式摆弄:
这里“this”位于内存中的两个不同位置,
而不是有一个内部联合/结构来保存值,这样很容易转换
来回(因为您对可移植性不感兴趣)
例如
编辑:名称“register”足够真实
don't do this
the 'this' pointer shouldn't be fiddled with in that way:
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)
e.g.
edit: true enough with the name 'register'
试试这个:
Try this: