问题
我正在使用 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
这些访问方法会被调用很多。我想利用指针()
来快速访问。我不想通过移位和 |'ing 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];
}
它工作得很好,但看起来很复杂,我相信还有更优雅的解决方案。
谢谢。