2

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

5 回答 5

10

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

于 2012-08-09T22:47:20.720 回答
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); 
于 2012-08-09T22:50:31.597 回答
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,因此您需要计算它。

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

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

于 2012-08-09T22:51:41.480 回答
1

因为 col 是 int32 +1 增加了 4 个字节的偏移量

在谷歌上搜索指针算法

于 2012-08-09T22:50:46.100 回答
1

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

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;

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

于 2012-08-09T23:16:21.070 回答