C ++将DWORD分解为字符

时间:2012-08-09 22:43:59

标签: c++ c algorithm memory

我有一个四字节的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);

5 个答案:

答案 0 :(得分:9)

抛弃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,您可以想象我们正在向左移动字节索引。

答案 1 :(得分: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); 

答案 2 :(得分:2)

向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上运行。

答案 3 :(得分:1)

因为col是int32 + 1,所以添加4字节的偏移量

在Google上搜索指针算术

答案 4 :(得分:0)

每个人都给出了不同的答案,而且所有答案都是正确的。有些是特定于字节序的(如按位操作)。其他人不是。为清楚起见,我可能会这样做:

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;

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