对同一数据有8位和16位视图?

时间:2015-08-08 18:41:44

标签: c++ arrays struct buffer 8-bit

问题

我正在使用C ++开发视频游戏模拟器。

内存由uint8_t值数组表示。通常,我还需要以16位值(两个连续的8位值)访问该存储器的内容。

我有一些看起来像这样的东西:

struct Memory {

  uint8_t map[0xFFFF];

  // Let's say that [] is for accessing 8-bit values
  uint8_t& operator[](uint16_t address) {
      return map[address];
  }

 // () is for 16-bit values
  uint16_t& operator()(uint16_t address) {
      return ???; // Looking for a good implementation here
  }
};

例如,如果内存包含[0xC0,0xFF,0x66,0xAA ...],那么[]将返回:

mem[0] -> 0xC0 mem[1] -> 0xFF mem[2] -> 0x66

()将返回(取决于系统字节顺序):

mem(0) -> 0xFFC0 mem(1) -> 0x66FF mem(2) -> 0xAA66

这些访问方法将被称为很多。我想利用()中的指针来快速访问。我不想通过移位和8位对来计算16位值(我不能因为方法必须返回引用)。

我的问题:在C ++中是否有办法在同一个缓冲区中拥有不同的视图?指向相同数据的8位视图和16位视图将是理想的。

(例如,JS ArrayBuffer API提供了DataView,它可以做到这一点。也许有一个聪明的技巧可以用C ++中的指针干净地实现它?)

尝试#1

我的第一个猜测是使用某种联盟:

union mem_t {
    uint8_t bytes[0xFFFF];
    uint16_t words[0x8000]
}

然后只能访问偶数字节的16位值:

mem.words[0] -> 0xFFC0

mem.words[1] -> 0xAA66 // Should be 0x66FF :(

尝试#2

一个可行的解决方案是为偶数和奇数地址增加两个16位指针,以处理重叠

uint16_t* even16 = (uint16_t*) map;
uint16_t* odd16 = (uint16_t*) (map + 1);

uint16_t& Memory::operator()(uint16_t address) {
    return address % 2 ? odd16[address / 2] : even16[address / 2];
}

它工作正常,但似乎非常复杂,我确信有更优雅的解决方案。

感谢。

1 个答案:

答案 0 :(得分:0)

这样的事情,但你可能会违反主机系统上的内存对齐规则:

struct Memory {

    uint8_t map[0xFFFF];

    // Let's say that [] is for accessing 8-bit values
    uint8_t& operator[](uint16_t address) {
        return map[address];
    }

    // () is for 16-bit values
    uint16_t& operator()(uint16_t address) {
        return *reinterpret_cast<uint16_t*>(&map[address]);
    }
};