2015-08-08 28 views
1

問題

我正在使用C++視頻遊戲模擬器。對同一數據有8位和16位的看法?

存儲器由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

這些訪問方法會得到所謂很多。我想利用三分球()快速訪問。我不想通過移位和計算的16位值|'荷蘭國際集團的8位對(我不能作爲該方法必須返回一個參考)。

我的問題:有沒有辦法在C++有不同的意見在同一個緩衝區?指向相同數據的8位視圖和16位視圖將是理想的。

(例如,JS ArrayBuffer API提供數據視圖,它可以只做到這一點。也許有一個聰明的把戲,在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]; 
} 

它的工作原理很好,但似乎非常複雜,我相信有更多優雅的解決方案。

謝謝。

+0

您是否在尋找'回報*(uint16_t *)映射[地址]'?你讓它太複雜了。 –

+0

謝謝你的建議伊戈爾,這工作正常。不過,我仍然對每種訪問都沒有投入的「懶惰」方法感興趣。 – merwaaan

+0

然後投它一次,並將其保存到一個指針... – deviantfan

回答

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]); 
    } 
}; 
+0

謝謝你的建議。這個reinterpret_cast與Igor的「原始」演員相比如何? – merwaaan

+0

@merwaaan實際上,它是一樣的。只是C只有這個「括號強制類型轉換」(類型)'而C++有三個額外的名字來表示演員的原因是什麼(以及一個真正的新的第四類演員,但不是重要的這裏) – deviantfan

+0

它幾乎完全一樣,但更明確一點。它在概念上是「更安全」的,因爲它不會拋棄常量 –