[英]C++ Breaking DWORD into characters
我有一個四字節的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);
拋棄memcpy
並使用位操作:
r = (col & 0x000000ff);
g = (col & 0x0000ff00) >> 8;
b = (col & 0x00ff0000) >> 16;
a = (col & 0xff000000) >> 24;
十六進制數中的ff
表示所有1
位的字節。 這和&
- 按位AND - 將使您不感興趣的字節 - 在每個位置 - 0
,並保留您感興趣的位。
>>
從左移零,將我們想要的字節放在最重要的位置,用於實際分配。 8個移位寬度為1個字節,16個為2個字節,24個為3個字節。
在視覺上,看着ff
,你可以想象我們正在將字節索引向左移動。
進行指針運算時,增量或減量的數量乘以指向的類型的大小。 將int32
指針強制轉換為char
指針,以便在col
的基址偏移一定距離處訪問char
大小的部分。
由於不同平台上的字節序差異,此技術可能很脆弱,因此我建議使用另一個答案中提供的更便攜的位掩碼操作。
// 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);
向int32添加+1將使地址增加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字節,64位整數也有64toh(),但該函數僅在Unix變種上退出我記得沒錯。)你需要做的就是int32 col = ntohl(color_mem[i]);
或者你可以根據這個來制作你的結構順序,但這樣你的代碼就無法在big-endian上運行。
因為col是int32 + 1,所以添加4個字節的偏移量
在谷歌上搜索指針算術
每個人都給出了不同的答案,而且所有答案都是正確的。 有些是特定於字節序的(如按位操作)。 其他人不是。 為清楚起見,我可能會這樣做:
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;
這是endian-neutral:它不依賴於整數的組織。 通常這很好,但你仍然需要意識到它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.