C++ 将DWORD分解为字符

C++ Breaking DWORD into characters

本文关键字:字符 分解 DWORD C++      更新时间:2023-10-16

我有一个四字节的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 是两个字节,24 是三个字节。

从视觉上看,看着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); 

将 +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 ,因此您需要计算这一点。

您可以使用网络转换函数将网络字节顺序(大端序)转换为主机字节顺序(小端序或大端序)。这样,您无需根据机器更改代码。(该函数是 Ntohl(网络到主机长),还有 hton(主机到网络短)等 2 字节,还有 64 位整数的 be64toh(),但如果我没记错的话,该函数仅在 Unix 变体上退出。您需要做的就是int32 col = ntohl(color_mem[i]);

或者你可以根据这个来制定你的结构顺序,但这样你的代码就不能在大端序上工作了。

因为 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;

这是字节序中性的:它不依赖于整数的组织。 通常这很好,但您仍然需要意识到这一点。