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

时间:2012-02-28 18:04:22

标签: c++

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

现在,好消息是所有这些寄存器都是很好地对齐的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
    }
};

我已经在一个较小的程序中使用更简单的方法验证了 this 指向Base实例,即使在派生对象的方法中使用它也是如此。如何确保 this 指向我正在尝试的操作的派生对象的开头?

我尝试了以下方法:

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

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

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

谢谢, 安迪

5 个答案:

答案 0 :(得分:2)

你应该使用工会吗?

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;
    }
};

答案 1 :(得分:1)

我只想在这里使用联盟:

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

另一件事:我认为你不应该混合像继承这样的高级构造和像位字段这样的低级构造。我建议创建一个POD RegisterValue struct / union,并将其作为接口类的成员。

答案 2 :(得分:1)

您的对象模型无法正确表示寄存器的内容

您的注册表有偏移量,驱动程序和内容。后者对于每种类型的寄存器可能有不同的布局,因此不能继承,但应按每个寄存器定义。

嵌套类是执行此操作的正确方法。

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
    }
};

答案 3 :(得分:0)

您只需查看struct的地址,就好像它们是DWORD一样,您可能会搞砸vtable等。为什么不在里面做union诀窍:使用位域创建struct并在DWORD内添加union。你会以这种方式安全。

答案 4 :(得分:0)

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

您不能直接“指针”到特定位。你可以模拟一个指针。

如前所述,请告诉您,您正在混合指针,位字段,结构,方法指针和放大器。类。就个人而言,我不使用“结构”作为“c ++公共类”,而是使用“纯c结构”。

请记住,位可以用作逻辑/布尔类型,大多数c / c ++编译器提供“bool”库(“sdbool.h”“&lt; stdbool&gt;”,“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
  }
};

老实说,有时,我使用无符号整数而不是位字段,特别是如果需要位域数组,并且必须使用较少的内存。

干杯。