2012-08-09 85 views
2

我有一個四字節的DWORD,我需要分成四個不同的字符。我以爲我知道如何做到這一點,但每次都得到奇怪的數字。這裏是我的代碼:C++打破DWORD爲字符

// The color memory 
    int32 col = color_mem[i]; 

    // The four destination characters 
    char r, g, b, a; 

    // Copy them in advancing by one byte every time 
    memcpy(&r, &col, 1); 
    memcpy(&g, &col + 1, 1); 
    memcpy(&b, &col + 2, 1); 
    memcpy(&a, &col + 3, 1); 
+1

什麼是color_mem的類型? – ryanbwork 2012-08-09 22:52:11

回答

8

memcpy和使用位操作:

r = (col & 0x000000ff); 
g = (col & 0x0000ff00) >> 8; 
b = (col & 0x00ff0000) >> 16; 
a = (col & 0xff000000) >> 24; 

ff在十六進制數字代表所有1位的字節。這和& - 位與 - 會讓你是不感興趣的字節 - 在每個位置 - 0,並保持你感興趣的位

>>輪換着從零左側,外放。我們想要的最重要位置的字節,用於實際分配。 8位移位一個字節的寬度,16位是兩個字節,24位是三個字節。

從視覺上看,在ff,你可以想象,我們走向左邊的字節索引。

+0

你能推薦一個關於這個主題的好教程嗎?似乎我應該知道的東西。 – 2012-08-09 22:51:24

+0

任何好的C書都會介紹這個,看看K&R的_The C Programming Language_。另外一個[這裏](http://www.cprogramming.com/tutorial/bitwise_operators.html) – pb2q 2012-08-09 22:52:53

+0

正如發佈這將工作,如果字節排序是big-endian;在小端平臺(x86,x64等)上,爲了與OP的意圖相匹配,您需要進行相反的處理:a =(col&0xff000000)>> 24; b =(col&0x00ff0000)>> 16; g =(col&0x0000ff00)>> 8; r =(col&0x000000ff);' – 2012-08-09 22:59:58

4

當您進行指針運算時,增量或減量的數量乘以指向的類型的大小。將int32指針指向char指針,以便訪問char大小的部件,其偏移距基地址爲col

由於不同平臺上字節序的差異,這種技術可能很脆弱,所以我建議使用另一個答案中提供的更便攜的位掩碼操作。

// The color memory 
int32 col = color_mem[i]; 

// The four destination characters 
char r, g, b, a; 

// Copy them in advancing by one byte every time 
memcpy(&r, (char*)&col, 1); 
memcpy(&g, ((char*)&col) + 1, 1); 
memcpy(&b, ((char*)&col) + 2, 1); 
memcpy(&a, ((char*)&col) + 3, 1); 
1

因爲山坳是一個Int32 +1增加了4個字節

搜索對谷歌

指針算術
2

添加+1到INT32將使地址去了4個字節的偏移量。

您可以使用memcpy(&g, reinterpret_cast<char *>(&col)+1, 1)等。

更好的辦法:

int32 col = color_mem[i]; 

struct splitted4byte 
{ 
    char r; 
    char g; 
    char b; 
    char a; 
} 

splitted4byte rgb; 

memcpy(&rgb, &col, 4); 

你應該關心的字節在col的方式順序。我不知道int32的哪個部分是哪種顏色。

你應該閱讀關於排序。 (谷歌它,有文件)

當R最高值和其他顏色爲0,如果它存儲爲1111 1111 0000 0000 0000 0000 0000 0000,我的意思是如果整數表示的顏色RGBA(255,0,0,0)等於這個二進制值。它將在內存中反向排序,即0000 0000 0000 0000 0000 0000 1111 1111,因此您需要計算此值。

您可以使用網絡轉換函數將網絡字節順序(big-endian)轉換爲主機字節順序(小端或大端)。這樣你就不需要根據機器來改變你的代碼。 (函數是ntohl(網絡到主機長),也有htons(主機到網絡短)等2字節,也有64toh()爲64位整數,但該函數只能退出Unix變種if我記得沒錯。) 所有你需要做的是int32 col = ntohl(color_mem[i]);

或者你可以使你的結構順序根據這個,但這樣你的代碼將無法在big-endian上工作。

0

每個人都給出了不同的答案,並且無論如何都是正確的。有些是特定於endian的(如按位操作)。其他人不是。爲了清楚起見,我可能做到這一點:

char *bytes = (char*)&color_mem[i]; 
char r = bytes[0]; 
char g = bytes[1]; 
char b = bytes[2]; 
char a = bytes[3]; 

我看不出有任何理由使用memcpy。即使有結構。結構分配是一種語言功能 - 您不必複製它。

還沒有看到工會的任何提及,可是...

union Pixel { 
    DWORD packed; 
    struct Components { 
     char r, g, b, a; 
    }; 
    char bytes[4]; 
}; 

// You can just specify your image data like this... 
Pixel *pixels = (Pixel*)color_mem; 

// Reference one pixel for convenience - don't need to reference, you can 
// just copy it instead if you want (alternative: Pixel p = pixels[i]) 
Pixel &p = pixels[i]; 

char r = p.r; 
char g = p.g; 
char b = p.b; 
char a = p.a; 

int32 col = p.packed; 

這是尾數中性的:它不依賴於一個整數的組織。通常這很好,但你仍然需要意識到它。