2013-11-09 18 views
1

按字節移動我有這個結構的共享內存(見codesnippet 1),所有值是十六進制值:c + +通過內存

Position 00: 55; // memory overall, byte 00 to 03; 
Position 01: 00; 
Position 02: 00; 
Position 03: 00; 
Position 04: 47; // memory for header information, byte 04 to 07; 
Position 05: 00 
Position 06: 00; 
Position 07: 00; 
Position 08: 00; // version, byte 08, 09; 
Position 09: 00; 
Position 0A: 64; // rate of refreshing memory between processes 
Position 0B: 00; 
Position 0C: 00; 
Position 0D: 00; 
Position 0E: 00; 
Position 0F: 4L; 
... 

正如你可以在我所知道的意見看哪個字節代表什麼樣的信息。無論如何,我把內存放在一個結構中(參見codesnippet 2)。此結構中的屬性當前是整數值。值55和47存儲在前兩個屬性中。看起來,'00'將被忽略,我無法逐字節地讀取整個存儲器。我如何按字節讀取內存?

codesnippet 2:

struct Shm { 
    int memorySize; // size of memory space; min 4 bytes, Position 00 - 03; ie 55 is a hex value and means 84 
    int headerSize; // size of header space; min 4 bytes, Position 04 - 07; ie 47 (hex), so 71 (dec) same number as config-dialog 
    int byte3; // version number 
    int byte4; // refreshing interval in msec 
    ... 

Moroever有在存儲部分地區,其中包含一些字符 - 怎麼投這些字節值字符和創建它們的話,目前我只能投到int值(參見codesnippet 3)

int main(void){ 
    std::cout << "*** Start SharedMemory ***\n"; 
    HANDLE hMapFile; 
    ... 
    Shm * pBuf = (Shm *) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE); 
    std::cout << " Debug memorySize " << ": " << dec << pBuf->memorySize << " (dec); " << hex << pBuf->memorySize << " (hex); " << &pBuf->memorySize << " (Adresse);\n"; // 84 Bytes 
    std::cout << " Debug headerSize " << ": " << dec << pBuf->headerSize << " (dec);  << hex << pBuf->headerSize << " (hex);\n"; // 71 Bytes 
    std::cout << " Debug byte3 " << ": " << dec << pBuf->byte3 << " (dec); " << hex << pBuf->byte3 << " (hex);\n"; 
    ... 
+1

根據你所看到的,你的版本看起來很短,而不是整數。 –

+0

感謝您的評論RetiredNinja,如何知道該版本是一個短而不是int?我猜是因爲它存儲在兩個字節而不是四個? – Jochen

+1

是的,如果你想讓你的結構與你所顯示的數據一致,那麼你需要適當地調整變量的大小。如果只有16位,那麼你需要一個16位的變量。當然,一旦你這樣做了,你需要打包結構來強制下一個int在short之後對齊。 –

回答

3

備註:將文件轉換爲struct是一個壞主意。對齊,int的大小,endian可以在不同的系統中有所不同。

鑄造到文件的任何部分:

const char * pBuf = (const char *) MapViewOfFile... 
const Mytype * myVar = (const Mytype *)(pBuf + myVarOffset); 

因此,對於字符串只需添加偏移PBUF(PBUF + myVarOffset - 是你所需要的) - 你得到開始指向字符串的指針。 (希望沒有在文件中的字符串的結束零字節)。

如果你的結構應該有一個緩衝/與非指定長度的字符串變量下面的代碼可能會有所幫助:

struct MyStruct 
{ 
    int size_of_string; 
    char my_string[1]; //can be used as a long string of size size_of_string 
}; 

注意sizeof(MyStruct)在這種情況下不會給你正確的值,所以你不能用'new'和堆棧分配這個對象(使用malloc/free來代替)。

我建議你閱讀關於序列化。

2

您可能有混疊和對齊問題。閱讀此瞭解更多詳情:strict aliasing and alignment

基本上,可以將內存複製到一個局部結構來避免這樣的問題:

Shm shmInfo; 

memcpy(&shmInfo,&pBuf[shmInfoOffset],sizeof(shmInfo)); 
+0

謝謝山姆,我試過你的想法,我想知道什麼值shmInfoOffset必須是,如果我想獲得索引3字節的值? – Jochen

+0

對不起,我想舉一個通用的例子。 'shmInfoOffset'只是該共享內存塊中'Shm'實例的偏移量。無論如何,它看起來像你的結構在偏移量'0',所以你可以通過'pBuf'。 'memcpy'會初始化該共享結構的本地副本。您不需要獲取單個字節,因爲您可以將'unsigned char'字段添加到結構中,也許使用'union',這將允許以四字節整數訪問單個字節。 – Sam

1

如果你處理的二進制數據,這是寫這樣的功能是一個好主意:

char getByte(char* data,int offset); 
void setByte(char* data,int offset,char value); 
char getWord(char* data,int offset); 
... 
void setLongword(char* ptr,int value); 

然後你就可以創建功能,讓您的代碼很易讀:

int getVersion(char* data) { 
    return (int)getByte(data,8); 
} 

爲此目的使用宏也不是一個壞主意。

1

如果你的字符在一個int中打包4個字節,那麼下面的例子可能會有所幫助。請注意,永久性必須是一個考慮因素。

#include <string> 
#include <iostream> 

void appendCharsFromInt(std::string& inString, int intAsChars, int charCount) 
{ 
    char someChars[4]; 
    memcpy(someChars, &intAsChars, sizeof(int)); 
    inString.append(someChars, charCount); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int byte0 = 0x6c6c6548; 
    int byte1 = 0x6f57206f; 
    int byte2 = 0x00646c72; 

    std::string completeString; 

    appendCharsFromInt(completeString, byte0, 4); 
    appendCharsFromInt(completeString, byte1, 4); 
    appendCharsFromInt(completeString, byte2, 4); 

    std::cout << completeString << std::endl; 

    return 0; 
} 
+0

感謝Chris O,你怎麼知道,byte0到byte2的值是多少? – Jochen

+0

我只是爲演示目的選擇了硬編碼值,但那些實際上來自您的'Shm'結構。 –