C 位数组宏,谁能解释一下它们是如何工作的?
我正在尝试为学校项目实现埃拉托斯特尼筛,我决定使用位数组来实现。当我寻找材料时,我遇到了这 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 中的按位运算有非常基本的了解(基本上我知道它们“存在”)。
这可以在使用不同字节序的另一个架构上工作吗? 提前致谢。
I'm trying to implement sieve of erathostenes for school project and I've decided to do so using bit arrays. While I was searching for materials, I came across these 3 macros, they work flawlessly, but I can't really read(understand) them.
#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;
Could you please explain to me at least one of them in detail, I have very basic knowledge about bitwise operations in C (basically I know they "exist").
Will this work on another architecture using different endianness?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
x
是字符数组。i
是位索引。由于每个char
都是 8 位,因此i
的最后 3 位定义了 char 中的位,其余位定义了数组中的 char。i>>3
将 i 向右移动 3 位,这样您就得到了告诉您哪个字符的部分,因此x[i>>3]
就是该字符包含由i
索引的位。i&7
是i
的最后 3 位(因为710==1112< /code>),所以它是字符中位的索引。
1<<(i&7)
是一个 char(实际上它是 int,但在这种情况下您可以忽略差异),它具有由i
索引的位,其余部分关闭。 (位掩码)char&mask
是检查位是否打开的常用方法。char|=mask
是打开位的常用方法。char&=~mask
是关闭位的常用方法,如果mask
是 char,则~mask==mask^0xFF
。我不认为这些宏是依赖字节序的。 (如果您通过将
int[]
转换为*char
获得x
,则情况不同)x
is array of chars.i
is an index of bits. since everychar
is 8 bits, the last 3 bits ofi
define the bit in the char, and the rest bits define the char in the array.i>>3
shift i 3 bits to the right, so you get the part that tell you which char, sox[i>>3]
is the char that contain the bit indexed byi
.i&7
is the last 3 bits ofi
(since710==1112
), so it's the index of the bit in the char.1<<(i&7)
is a char (truly it's int, but in this context you can ignore the difference), that has the bit indexed byi
on, and the rest bits off. (the mask of the bit)char&mask
is the common way to check if bit is on.char|=mask
is the common way to turn bit in.char&=~mask
is the common way to turn bit off, and ifmask
is char, then~mask==mask^0xFF
.I don't think that these macros are endiannes-depend. (if you got
x
by convertingint[]
to*char
, it's a different story)首先,这些宏邪恶地假设
CHAR_BIT == 8
和i >>> 。 3
实际上是i / 8
。 (所以实际上这段代码应该是i / CHAR_BIT
。)第一个表达式计算包含所需位的 byte,因此是数组中的数组索引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 ,所以我们在第六个字节,并且i % CHAR_BIT
是 3,所以我们正在查看第六个字节的第四位。实际的位摆弄本身做了通常的事情;例如,对给定位的测试使用适当的位模式执行按位与(即第 k 位的
1 << k
);设置该位使用按位或,而将其归零则需要更多的参与(想一想!)。First off, those macros assume evilly that
CHAR_BIT == 8
, andi >> 3
is actuallyi / 8
. (So really this code should sayi / CHAR_BIT
.) This first expression computes the byte which contains your desired bit, and is thus the array index in your arrayx
(which should be an array ofunsigned char
!).Now that we've selected the correct byte, namely
x[i >> 3]
(orx[i / CHAR_BIT]
in your own, better code), we have to do the bit-fiddling. Again,i & 7
really wants to bei % CHAR_BIT
, and it extracts only the remainder of your bit count that gives you the offset within the byte.Example. Requesting the 44th bit with
i = 43
, and assumingCHAR_BIT = 8
,i / CHAR_BIT
is 5, so we're in the sixth byte, andi % CHAR_BIT
is 3, so we're looking at the fourth bit of the sixth byte.The actual bit-fiddling itself does the usual stuff; e.g. testing for a given bit performs bit-wise AND with the appropriate bit pattern (namely
1 << k
for thek
th bit); setting the bit uses bit-wise OR, and zeroing it requires something a tiny bit more involved (think about it!).;
;
after the last macro