-4

我在处理遗留代码时遇到了以下 C 函数,我完全困惑,代码的组织方式。我可以看到该函数正在尝试在位流中的给定位置设置位,但我无法理解各个语句和表达式。有人可以解释为什么开发人员在这里和那里使用除以 8 (/8) 和模 8 (%8) 表达式。有没有一种简单的方法可以在 c 中读取这些类型的位操作函数?

static void setBits(U8 *input, U16 *bPos, U8 len, U8 val)
{
  U16 pos;
  if (bPos==0)
  {
    pos=0;
  }
  else
  {
    pos = *bPos;
    *bPos += len;
  }
  input[pos/8] = (input[pos/8]&(0xFF-((0xFF>>(pos%8))&(0xFF<<(pos%8+len>=8?0:8-(pos+len)%8)))))
                |((((0xFF>>(8-len)) & val)<<(8-len))>>(pos%8));
  if ((pos/8 == (pos+len)/8)|(!((pos+len)%8)))
    return;
  input[(pos+len)/8] = (input[(pos+len)/8]
                        &(0xFF-(0xFF<<(8-(pos+len)%8))))
                       |((0xFF>>(8-len)) & val)<<(8-(pos+len)%8);
}
4

1 回答 1

2

请解释为什么开发人员在这里和那里使用除以 8 (/8) 和模 8 (%8) 表达式

首先,请注意字节的各个位编号为 0 到 7,其中位 0 是最低有效位。一个字节有 8 位,因此是“幻数”8。

一般来说:如果您有任何原始数据,它由n字节组成,因此始终可以被视为字节数组uint8_t data[n]。要访问x该字节数组中的位,您可以例如这样做:

给定x = 17,然后在字节数中找到位 x 17/8 = 2。请注意,整数除法“下限”该值,而不是 2.125 你得到 2。

整数除法的余数为您提供该字节中的位位置,17%8 = 1.

所以第 17 位位于字节 2,位 1。data[2]给出了字节。

为了从 C 中的字节中屏蔽位,使用按位 AND 运算符&。为了使用它,需要一个位掩码。这种位掩码最好通过将值 1 移动所需的位数来获得。位掩码可能最清楚地以十六进制表示,一个字节的可能位掩码将是(1<<0) == 0x01(1<<1) == 0x02(1<<3) == 0x04等等(1<<4) == 0x08

在这种情况下(1<<1) == 0x02

C代码:

uint8_t data[n];
...
size_t  byte_index = x / 8;
size_t  bit_index  = x % 8;
bool    is_bit_set;

is_bit_set = ( data[byte_index] & (1<<bit_index) ) != 0;
于 2015-06-15T08:01:29.693 回答