使用此指针指向类中的位字段

Using this pointer to point to a bit field within a class

本文关键字:字段 指针      更新时间:2023-10-16

我正在进行的项目需要将许多不同的硬件寄存器作为类对象表示给我们的用户。我几乎完成了我的对象模型,但我遇到了一个障碍,我还不确定如何超越它。这些寄存器是使用结构公开的。所有这些寄存器结构都将继承自一个基结构,该基结构将提供有用的东西,例如如何从内存中获取特定的寄存器值并将其存储到位字段。

现在,好的事情是所有这些寄存器都是很好地对齐的DWORD。所以,我的代码是这样的:

struct Base {
    DWORD offset;
    Driver* pToDrv;
    // methods to set/get values to the registers using the driver pointer
    void SetRegister(DWORD val);
};

struct Register1 : public Base {
    DWORD bit0           : 1;
    DWORD bit1           : 1;
    // etc. until 32 bits
    DWORD bit31          : 1;
    // getters/setters for the individual bits
    void SetFullRegister(DWORD val) {
        *(reinterpret_cast<DWORD*>(this)) = val; // uh-oh!  This doesn't point to bitfield
        SetRegister(reinterpret_cast<DWORD*>(this)); // same thing here
    }
};

我已经在一个较小的程序中用一种更简单的方法验证了这个即使在派生对象的方法中使用时也指向Base实例。如何确保this指向我尝试执行的操作的派生对象的开始?

我尝试了以下方法:

*(reinterpret_cast<DWORD*>(this + sizeof(Derv))) = val;

虽然看起来没有什么不好的事情发生,但最终的结果是什么都没有发生。我知道这不是真的,因为值被分配到了某个地方,但尴尬的是,我不知道在哪里。这显然不起作用,也不是一种安全的方法。

如果我没有充分描述我的问题,请告诉我。

谢谢,Andy

您是否应该使用联合?

struct Register1 : public Base {
    union {
      struct Bits {
        DWORD bit0           : 1;
        DWORD bit1           : 1;
        // etc. until 32 bits
        DWORD bit31          : 1;
      };
      DWORD dwReg;
    } Reg;
    // getters/setters for the individual bits
    void SetFullRegister(DWORD val) {
      Reg.dwReg = val;
    }
};

您的对象模型不能正确地表示寄存器的内容

您的寄存器有一个偏移量、一个驱动程序和内容。后者对于每种类型的寄存器可能有不同的布局,因此不能继承,但应该在每个寄存器的基础上定义。

嵌套类是一种正确的方法。

struct Register1 : public Base {
    struct Content {
      DWORD bit0           : 1;
      DWORD bit1           : 1;
      // etc. until 32 bits
      DWORD bit31          : 1;
    } content;
    // getters/setters for the individual bits
    void SetFullRegister(DWORD val) {
        *(reinterpret_cast<DWORD*>(&content)) = val; // This points to bitfield
        SetRegister(reinterpret_cast<DWORD*>(&content)); // same thing here
    }
};

我只需要在这里使用一个并集:

union RegisterValue {
  struct {
    DWORD bit0 : 1;
    // ...
  };
  DWORD Full;
};

另一件事是:我认为不应该将继承之类的高级构造和位字段之类的低级构造混合在一起。我建议制作一个POD RegisterValue结构/联合,并将其作为接口类的成员。

只需将structs的地址视为DWORDs,就有可能弄乱vtables等。为什么不在里面做union技巧呢:创建一个带有位字段的struct,并在union中添加DWORD。这样你就安全了。

似乎你同时做了太多的事情,这使得解决这篇文章的主要问题变得困难。

您不能直接"指针"指向特定的位。您可以模拟一个位指针。

正如前面的答案所告诉你的,你正在混合指针、位字段、结构、方法指针&类。就我个人而言,我不使用"structs"作为"c++公共类",而是使用"纯c structs"。

请记住,位可以用作逻辑/布尔类型,大多数c/c++编译器都提供一个"bool"库("sdbool.h"<stdbool>","bool.h")。

 // "pure c" style
struct registertype
{
      DWORD bit0           : 1;
      DWORD bit1           : 1;
      // etc. until 32 bits
      DWORD bit31          : 1;
};
// "c++" wrapper style
class registerclass
{
  registertype data;
  public:
  registerclass (DWORD fullvalue)
  {
    // assign values to each bit
  }
  bool getBit(int bitnumber)
  {
    // recover value from a specific bit
  }
  void setBit(int bitnumber, bool BitValue)
  {
    // assign values to a specific bit
  }
};

老实说,有时,我会使用无符号整数而不是位字段,特别是如果需要位字段数组,那么就必须使用尽可能少的内存。

干杯。