1

The project I'm working on has a need to represent many different hardware registers to our users as class objects. I'm nearly done on my object model, but I'm at one hurdle that I'm not sure how to surpass yet. These registers are exposed using structures. All of these register structures will inherit from a base struct which will provide useful things like how to get the particular register value from memory and store it to the bit field.

Now, the nice thing is that all of these registers are nicely aligned DWORDs. So, my code is something like this:

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

I've verified with a simpler approach in a smaller program that this points to the Base instance even when used in the derived object's methods. How do I ensure that this points to the start of the derived object for the operations I'm trying to do?

I've tried the following approach:

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

Although nothing bad seemingly happened, the net result was that nothing at all happened. I know this isn't true because the value was assigned somewhere but, cringe, I've no idea where. This obviously isn't working nor is it a safe approach.

Please let me know if I've not adequately described my problem.

Thanks, Andy

Andrew Falanga
  • 2,274
  • 4
  • 26
  • 51

5 Answers5

2

may be you should use unions?

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;
    }
};
Andrey Starodubtsev
  • 5,139
  • 3
  • 32
  • 46
  • 1
    NO! a union should ONLY be read from the last type it was written to. If this works, it's implementation defined. (oh yes, I know everyone does it this way. It's not C++.) – xtofl Feb 28 '12 at 18:15
  • Apart from some references to the standard at SO (http://stackoverflow.com/a/740686/6610), I found a real case in the Qt code: http://qt.gitorious.org/qt/qt/commit/c1b067ea8169e1d37e2a120334406f1f115298bb – xtofl Feb 28 '12 at 18:47
  • Very interesting, thanks! Found detailed article about this commit - http://labs.qt.nokia.com/2011/06/10/type-punning-and-strict-aliasing/ – Andrey Starodubtsev Feb 28 '12 at 20:37
1

I would simply use a union here:

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

Another thing: I don't think you should mix high-level constructs like inheritance and low-level constructs like bit fields. I'd recommend making a POD RegisterValue struct/union and having that as a member of your interface classes.

Philipp
  • 48,066
  • 12
  • 84
  • 109
  • Agree with the mix-avoidance. Disagree with the union piece, which is non-standard hence non-guaranteed way to `reinterpret` a value. – xtofl Feb 28 '12 at 18:18
1

Your object model doesn't represent the content of the register correctly.

Your register has an offset, and a driver, and content. The latter may have a different layout for each type of register, so can't be inherited but should be defined on a per-register basis.

A nested class is a proper means to do that.

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
    }
};
xtofl
  • 40,723
  • 12
  • 105
  • 192
  • Thank you. This approach, I believe, solves the problem. I knew there was an easy answer that I'd overlooked. This works in the scaled down version I was testing in. Now, to integrate with the bigger, uglier, program. – Andrew Falanga Feb 28 '12 at 20:52
0

You risk messing up with vtables and the likes, by simply looking at the addresses of your structs as if they were DWORDs. Why not do an union trick inside: create a struct with the bitfields and add that plus a DWORD inside an union. You'll be safe in this way.

foxx1337
  • 1,859
  • 3
  • 19
  • 23
0

Seems that you are doing too many things, at the same time, and that's making difficult to solve the main question of this post.

You cannot "pointer" directly to an specific bit. You may simulate a bit pointer.

As previous answers, tell you, you are mixing pointers, bit-fields, structs, method pointers & classes. Personally, I don't use "structs" as "c++ public classes", but, as "pure c structs".

Remember that bits may be used as logical / boolean types, and most c/c++ compilers, provide a "bool" library ( "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
  }
};

To be honest, sometimes, I use unsigned integers instead of bit fields, specially, if arrays of bitfields, are required, and its necesary to use the less memory possible.

Cheers.

umlcat
  • 4,091
  • 3
  • 19
  • 29