如何设置、清除和切换一点?


当前回答

将第n位设置为x(位值),不使用-1

有时,当您不确定-1或类似的结果时,您可能希望在不使用-1的情况下设置第n位:

number = (((number | (1 << n)) ^ (1 << n))) | (x << n);

解释:((number |(1<<n)将第n位设置为1(其中|表示逐位OR),然后使用(…)^(1<<n)将将第n个位设置为0,最后通过(…)|x<<n,将第n比特设置为0(位值)x。

这也适用于戈朗。

其他回答

更一般地,对于任意大小的位图:

#define BITS 8
#define BIT_SET(  p, n) (p[(n)/BITS] |=  (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] &   (0x80>>((n)%BITS)))

将第n位设置为x(位值),不使用-1

有时,当您不确定-1或类似的结果时,您可能希望在不使用-1的情况下设置第n位:

number = (((number | (1 << n)) ^ (1 << n))) | (x << n);

解释:((number |(1<<n)将第n位设置为1(其中|表示逐位OR),然后使用(…)^(1<<n)将将第n个位设置为0,最后通过(…)|x<<n,将第n比特设置为0(位值)x。

这也适用于戈朗。

对于初学者,我想用一个例子解释一下:

例子:

value is 0x55;
bitnum : 3rd.

使用&运算符检查位:

0101 0101
&
0000 1000
___________
0000 0000 (mean 0: False). It will work fine if the third bit is 1 (then the answer will be True)

切换或翻转:

0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)

|运算符:设置位

0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)

这是我最喜欢的位算术宏,它适用于从无符号字符到size_t的任何类型的无符号整数数组(这是应该有效使用的最大类型):

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))

要设置位:

BITOP(array, bit, |=);

要清除一点:

BITOP(array, bit, &=~);

要切换一位,请执行以下操作:

BITOP(array, bit, ^=);

要测试一点:

if (BITOP(array, bit, &)) ...

etc.

比特场方法在嵌入式领域还有其他优势。您可以定义直接映射到特定硬件寄存器中的位的结构。

struct HwRegister {
    unsigned int errorFlag:1;  // one-bit flag field
    unsigned int Mode:3;       // three-bit mode field
    unsigned int StatusCode:4;  // four-bit status code
};

struct HwRegister CR3342_AReg;

您需要注意位打包顺序-我认为它首先是MSB,但这可能取决于实现。此外,验证编译器处理程序字段如何跨越字节边界。

然后,您可以像以前一样读取、写入和测试各个值。