首先,我不关心可移植性,并且可以安全地假设字节序不会改变。 假设我读取了一个硬件寄存器值,我想将这个寄存器值覆盖在位域上,以便我可以在不使用位掩码的情况下引用寄存器中的各个字段。
编辑:修正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; }最满意答案
不要这样做
*this = *(reinterpret_cast<HW_Register*>(®isterValue));不应该用这种方式弄乱'this'指针:
HW_Register reg(val) HW_Register *reg = new HW_Register(val)这里'这'是在记忆中的两个不同的地方
相反,有一个内部联合/结构来保存价值,这种方式很容易来回转换(因为你对可移植性不感兴趣)
例如
union { struct { unsigned short field1:2; unsigned short field2:4; unsigned short field3:2; ... } bits; unsigned short value; } reg编辑:真正足够的名字'登记'
don't do this
*this = *(reinterpret_cast<HW_Register*>(®isterValue));the 'this' pointer shouldn't be fiddled with in that way:
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)
e.g.
union { struct { unsigned short field1:2; unsigned short field2:4; unsigned short field3:2; ... } bits; unsigned short value; } regedit: true enough with the name 'register'
更多推荐
发布评论