一块给定的bit区间,判断该区间的bit位是否全部为0.
区间分为 [ start, end) // 与C语言中的区间的越界规则一致,但是不便于处理
或者[start, end] //便于字节的处理
思路: 将位区间转化为字节操作, 对开始和末尾字节进行位模式操作后与0比较, 中间的字节与0直接比较。
注意点: 1. 转化为字节时,未必为整数个字节。 注意区间的开始字节和结尾字节,可能只有部分位有效。
2. 对于完整的字节,与0比较;
3. 起始字节与其区间有效位生成的字节mask ,进行按位& 操作, 然后与0比较。
4. 结尾字节与其区间有效位生成的字节mask ,进行按位& 操作, 然后与0 比较。
5. 区间在即同一个字节内,要单独处理。
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef unsigned char uint8_t;
int bit_range_zero(uint8_t *buf, int start, int end);
int bit_range_zeros(uint8_t *buf, int start, int end);
int main(int argc, char *argv[], char *env[])
{
uint8_t buf[100] = {0x81, 0x82, };
printf("%d \n", bit_range_zero(buf, 0, 2));
printf("%d \n", bit_range_zeros(buf, 0, 2));
printf("\n\n");
printf("%d \n", bit_range_zero(buf, 1, 6));
printf("%d \n", bit_range_zeros(buf, 1, 6));
printf("\n\n");
printf("%d \n", bit_range_zero(buf, 1, 7));
printf("%d \n", bit_range_zeros(buf, 1, 7));
printf("\n\n");
printf("%d \n", bit_range_zero(buf, 1, 8));
printf("%d \n", bit_range_zeros(buf, 1, 8));
return 0;
}
// output 0, if the bits [start, end) all to be zeros. otherwise -1.
int bit_range_zero(uint8_t *buf, int start, int end) {
assert(start < end);
int start_byte = start / 8;
int end_byte = end / 8;
int i;
uint8_t start_mask = 0xff >> (start % 8);
uint8_t end_mask = 0xff << (8 - (end % 8));
//printf("bit_range: [%i, %i), byte_range: [%i, %i] \n", start, end, start_byte, end_byte);
//printf("start_byte mask: 0x%02x \n end_byte mask: 0x%02x\n", start_mask, end_mask);
if(start_byte == end_byte) { //bit range [start, end) in the same byte
uint8_t byte_mask = ~(start_mask ^ end_mask);
//printf(" same_byte mask: 0x%02x \n", byte_mask);
if( (buf[start_byte] & byte_mask) != 0) return -1;
}else {// bit range[start, end) in different bytes
if ((buf[start_byte] & start_mask) != 0) {
return -1;
}
if ((buf[end_byte] & end_mask) != 0) {
return -1;
}
for (i = start_byte + 1; i < end_byte; i++) {
if (buf[i] != 0) return -1;
}
}
return 0;
}
// output 0, if the bits [start, end] all to be zeros. otherwise -1.
int bit_range_zeros(uint8_t *buf, int start, int end) {
assert(start < end);
int start_byte = start / 8;
int end_byte = end / 8;
int i;
uint8_t start_mask = 0xff >> (start % 8);
uint8_t end_mask = 0xff << (7 - (end % 8));
//printf("bit_range: [%i, %i], byte_range: [%i, %i] \n", start, end, start_byte, end_byte);
//printf("start_byte mask: 0x%02x \n end_byte mask: 0x%02x\n", start_mask, end_mask);
if(start_byte == end_byte) { //bit range [start, end] in the same byte
uint8_t byte_mask = ~(start_mask ^ end_mask);
//printf(" same_byte mask: 0x%02x \n", byte_mask);
if( (buf[start_byte] & byte_mask) != 0) return -1;
}else { // bit range[start, end) in different bytes
if ((buf[start_byte] & start_mask) != 0) {
return -1;
}
if ((buf[end_byte] & end_mask) != 0) {
return -1;
}
for (i = start_byte + 1; i < end_byte; i++) {
if (buf[i] != 0) return -1;
}
}
return 0;
}