c++ - 如何将 4 个 2 位值合并为 1 个 8 位值?

标签 c++ c bit-manipulation bit bit-shift

这段代码是我用来将 4 个 2 位值(无符号字符,但它们只包含 0-3 的值)组合成 1 个无符号字符值

unsigned char nibble = 0;

nibble = (nibble & 0x03) | (output[i] & 0x03);
nibble = (nibble & 0x0C) | (output[i+1] & 0x03) << 2);
nibble = (nibble & 0x30) | (output[i+2] & 0x03) << 4);
nibble = (nibble & 0xC0) | (output[i+3] & 0x03) << 6);

它为除 00 00 00 00 之外的所有内容生成不正确的值(它通常为 2 组不同的 2 位值生成相同的结果)。

我很困惑,因为上面的代码是对 this code 的编辑,这可以很好地将 2 个 4 位值组合成 1 个字节,那么为什么我的版本不能将 4 个 2 位值组合成 1 个字节?

char byte;
byte = (byte & 0xF0) | (nibble1 & 0xF); // write low quartet
byte = (byte & 0x0F) | ((nibble2 & 0xF) << 4); // write high quartet

我已经尝试将 0x03/0x0C/0x30/0xC0 更改为 0xC0/0x30/0x0C/0x03,仍然错误。将 & 0x03 更改为 & 0xC0 也是如此。

最佳答案

这是因为你每次都清除半字节中的位。

也就是说,当你这样说时:

nibble = (nibble & 0xC0)

你真正想说的是“放弃我到目前为止所做的所有工作,除了位置 3 和 4 的位”。

此代码(未经测试)可能会解决您的问题:

unsigned char nibble = 0;

nibble |= (output[i  ] & 0x03);
nibble |= (output[i+1] & 0x03) << 2;
nibble |= (output[i+2] & 0x03) << 4;
nibble |= (output[i+3] & 0x03) << 6;

如果 确实 output[i+x] 仅包含 [0,3] 范围内的值,那么您可以更改代码如下:

unsigned char nibble = 0;

assert(0<=output[i  ] && output[i  ]<=3)
nibble |= output[i  ];
assert(0<=output[i+1] && output[i+1]<=3)
nibble |= output[i+1] << 2;
assert(0<=output[i+2] && output[i+2]<=3)
nibble |= output[i+2] << 4;
assert(0<=output[i+3] && output[i+3]<=3)
nibble |= output[i+3] << 6;

当然,如果您真的,真的确定,可以删除断言。但您也可以保留它们,让编译器使用 NDEBUG 标志 (g++ -DNDEBUG mycode.cpp) 消除它们。参见 this question了解更多详情。

关于c++ - 如何将 4 个 2 位值合并为 1 个 8 位值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45603191/

相关文章:

C - 如何从指向该值的指针访问值?

c - C 左移运算中的模行为

c++ - 像键盘一样向 cpu 发送中断?

c - 如何在 OpenGL 中使用嵌套循环用较小的正方形列表填充平面?

C++ const int 不可用于常量表达式

c - 如何使用 FreeIPMI API 防止 ipmi 传感器输出到标准输出

Java随机序列

c++ - 将 1 到 32 位数字附加到 char 缓冲区

c++ - 带有 MinGW 4.8 的 Windows 上的模板 undefined reference

c++ - 如何在 C++ 中获取 OpenGL 使用的总内存(以字节为单位)?