C++ 将DWORD分解为字符
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 是两个字节,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;
这是字节序中性的:它不依赖于整数的组织。 通常这很好,但您仍然需要意识到这一点。
- 通过递归进行因子分解
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 有人能分解一下这个c++模板的语法吗
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 指向指向字符数组的指针数组的指针
- 如何用转义符替换字符串中的所有特殊字符
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 比较字符数组
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 精神语法按字符数量分解字符串
- C++ 将DWORD分解为字符
- 要分解为3个整数变量的字符数组