我正在尝试为学校项目实施一些用于测试的方法,我决定使用位数组来实现。在我搜索材料时,我遇到了这3个宏,它们完美无缺,但我无法真正阅读(理解)它们。
#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0)
#define SETBIT(x,i) x[i>>3]|=(1<<(i&7));
#define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7))^0xFF;
请你详细解释一下至少其中一个,我对C中的按位操作有基本的了解(基本上我知道它们“存在”)。
这会在另一个使用不同字节序的架构上工作吗? 提前谢谢。
答案 0 :(得分:5)
x
是一系列字符。 i
是位的索引。由于每个char
是8位,i
的最后3位定义了char中的位,其余位定义了数组中的char。
i>>3
向右移动3位,因此您获得了告诉您哪个字符的部分,因此x[i>>3]
是包含由i
索引的位的字符。
i&7
是i
的最后3位(自710==1112
起),因此它是char中位的索引。 1<<(i&7)
是一个char(真的是int,但在这个上下文中你可以忽略它的区别),它的位被i
打开,其余位被关闭。 (比特的面具)
char&mask
是检查位是否打开的常用方法。
char|=mask
是改变位置的常用方法。
char&=~mask
是关闭位的常用方法,如果mask
是char,那么~mask==mask^0xFF
。
我不认为这些宏是依赖于endiannes的。 (如果您通过将x
转换为int[]
来获得*char
,那就是另一个故事了)
答案 1 :(得分:4)
首先,这些宏假设CHAR_BIT == 8
,而i >> 3
实际上是i / 8
。 (所以这段代码应该说i / CHAR_BIT
。)第一个表达式计算包含所需位的字节,因此是数组x
中的数组索引(应该是是unsigned char
的数组!)。
现在我们已经选择了正确的字节,即x[i >> 3]
(或者你自己的x[i / CHAR_BIT]
,更好的代码),我们必须做一点点。同样,i & 7
确实希望成为i % CHAR_BIT
,并且它只提取位数的剩余部分,它会在字节内提供偏移。
示例。使用i = 43
请求第44位,并假设CHAR_BIT = 8
,i / CHAR_BIT
为5,因此我们位于第6个字节,{ {1}}是3,所以我们看第六个字节的第四位。
实际的比特摆弄本身就是常见的东西;例如测试给定位以适当的位模式执行逐位AND(即i % CHAR_BIT
位的1 << k
;设置该位使用逐位OR,并将其归零需要更多的参与(想一想!)。
答案 2 :(得分:-1)
#define ISBITSET(x,i) (((x)[(i) / CHAR_BIT] & (1u << ((i) % CHAR_BIT))) != 0)
#define SETBIT(x,i) (x)[(i) / CHAR_BIT] |= (1u << ((i) % CHAR_BIT);
#define CLEARBIT(x,i) (x)[(i) / CHAR_BIT] &= ~(1u << ((i) % CHAR_BIT))
;