【问题标题】:Read a single bit from a buffer of char从 char 的缓冲区中读取一个位
【发布时间】:2016-02-12 22:08:41
【问题描述】:

我想实现这样的功能:

int read_single_bit(unsigned char* buffer, unsigned int index)

其中 index 是我想要读取的位的偏移量。

如何使用位移位或掩码来实现此目的?

【问题讨论】:

  • 你的实现有什么问题?
  • 使用无符号整数的好开始。你似乎也知道你​​需要什么。现在开始编写代码。

标签: c arrays bitmask


【解决方案1】:

您可能希望将其拆分为三个单独的任务:

  1. 确定哪个char 包含您要查找的位。
  2. 确定您需要读取的char 的位偏移量。
  3. 实际上是从char 中选择了那个位。

我将把第 (1) 和 (2) 部分留作练习,因为它们还不错。对于第 (3) 部分,您可能会发现有用的一个技巧是在所讨论的字节和您想要的索引处具有单个 1 位的字节之间进行按位与操作。例如,假设您想从一个字节中取出第四位。然后你可以这样做:

Byte:   11011100
Mask:   00001000
----------------
AND:    00001000

因此请考虑以下问题:如果您知道位索引,您将如何生成所需的掩码?以及如何将 AND 结果转换回单个位?

祝你好运!

【讨论】:

  • 有趣,你确实写了一个很好的答案。
【解决方案2】:
buffer[index/8] & (1u<<(index%8))

应该这样做(即,将buffer 视为一个位数组并测试index 处的位)。

同样:

buffer[index/8] |= (1u<<(index%8))

应该设置index-th 位。

或者您可以存储一个表,其中包含 1 和 &amp; 的八个移位状态

unsigned char bits[] = { 1u<<0, 1u<<1, 1u<<2, 1u<<3, 1u<<4, 1u<<5, 1u<<6, 1u<<7 }; 

如果您的编译器没有将/% 优化为位操作(更高效),那么:

 unsigned_int / 8  == unsigned_int >> 3
 unsigned_int % 8  == unsigned_int & 0x07  //0x07 == 0000 0111

所以

 buffer[index>>3] & (1u<<(index&0x07u))  //test
 buffer[index>>3] |= (1u<<(index&0x07u)) //set

【讨论】:

  • 左移是 mod 8?
  • 嗯,再想想,我不这么认为。但是你知道为什么实际上不知道吗?如果有其他较小的限制,您将拥有 UB。您应该更安全地编写代码。 (抱歉,必须进行虚拟编辑才能删除 DV。
  • OP 将索引声明为 unsigned intbuffer 作为无符号字符数组。无符号整数的位操作应该没有问题。
  • 哦,你的有符号算术做得很好。这是一个非常善意的提示,可以研究任何原因(这是非常重要的知识,没有恶意)。
  • @Olaf 我想我知道你在暗示什么。 1 字面量是 signed int,如果左移的位命中符号位,我会使用 UB,但这不是因为幸运的是我只移动了低 8 位,但我还是有更好的写1u,对吗?
【解决方案3】:

您的函数的一种可能实现可能如下所示:

int read_single_bit(unsigned char* buffer, unsigned int index)
{
    unsigned char c = buffer[index / 8]; //getting the byte which contains the bit
    unsigned int bit_position = index % 8; //getting the position of that bit within the byte

    return ((c >> (7 - bit_position)) & 1);
    //shifting that byte to the right with (7 - bit_position) will move the bit whose value you want to know at "the end" of the byte.
    //then, by doing bitwise AND with the new byte and 1 (whose binary representation is 00000001) will yield 1 or 0, depending on the value of the bit you need.
}

【讨论】:

  • 不要在不需要并且确切知道自己在做什么的情况下混合签名和未签名。
猜你喜欢
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
  • 2012-10-04
相关资源
最近更新 更多