使用按位操作编程时,我有一个疑问。也就是说,在我的项目中,在某个时间点我需要设置这样的位,如果输入'1'则表示第1位已设置。如果我输入'2',则表示前2位已设置。
所以,
1-1 2-11 3-111 4-1111
同样如此。由此我分析了以下模式。这是1-1,11-3,111-7,1111-15。
那是2 ^ 1-1 = 1,2 ^ 2-1 = 3,2 ^ 3-1 = 7,......
现在我需要在一行中为这种格式编写按位运算。
感谢任何帮助。
答案 0 :(得分:3)
到目前为止,我们已经有了主要的两个答案&#34;你经常会遇到这个问题。他们的边缘条件不同。假设32位无符号整数采用一些常见的方法,(1u<<n)-1
答案可以处理0到31,0xFFFFFFFF>>(32-n)
答案可以处理1到32。
经常出现的一个问题是,我们可以有0到32吗?
你可以,但自然会更复杂,特别是如果你不接受条件。通过将这两种方法与三元运算符相结合,可以很容易地实现全范围,但如果没有这种方法,还有很多方法。
请注意,n=32
是0b00100000
中设置位n
的唯一情况。
所以我们可以做的一件事是提取该位,将其反转,然后向左移动(小心不要执行未定义的移位),如下所示:
((n >> 5 ^ 1) << (n & 31)) - 1
现在,如果n < 32
,它会简化为旧的(1u << n) - 1
。如果n == 32
,它会简化为(0 << irrelevant) - 1
,其中irrelevant
恰好为0,但我们可以选择0到31之间的任何内容。
在某些语言(特别是C#和Java)中,定义了一个或多个整数的宽度,并且可以删除& 31
。在某些汇编语言中,例如PowerPC,按整数宽度移动会得到0,在这种情况下,等效于(1u << n) - 1
的汇编级别将按原样工作。
在其他汇编语言中,可能还有其他技巧,通常使用在高级语言中没有直接等效的特殊指令。例如,在带有BMI1的x86上:
or rax, -1
shl ecx, 8
bextr rax, rax, rcx
或者在带有BMI2的x86上:
or rax, -1
bzhi rax, rax, rcx
答案 1 :(得分:1)
1 << n
提供了2 ^ n
,因此您可能需要2 ^ n - 1
这一个:
static inline unsigned int test(int n)
{
return (1u << n) - 1;
}
答案 2 :(得分:1)
使用unsigned int(比如说32位),你可以从bitcount获取值,如下所示:
value = 0xffffffffU >> (32-bitcount);
例如,让我们使用bitcount
3:
0xffffffff >> (32-bitcount)
= 0xffffffff >> 29
= 0x00000007
以下程序显示了这一点:
#include <stdio.h>
int cvt (int bc) {
return 0xffffffffU >> (32-bc);
}
int main (void) {
for (int bc = 1; bc <= 32; bc++)
printf ("%2d: 0x%08x %u\n", bc, cvt (bc), cvt (bc));
return 0;
}
该程序的输出显示每个后续的bitcount在右侧再添加一个1-bit
:
1: 0x00000001 1
2: 0x00000003 3
3: 0x00000007 7
4: 0x0000000f 15
5: 0x0000001f 31
6: 0x0000003f 63
7: 0x0000007f 127
8: 0x000000ff 255
9: 0x000001ff 511
10: 0x000003ff 1023
11: 0x000007ff 2047
12: 0x00000fff 4095
13: 0x00001fff 8191
14: 0x00003fff 16383
:
30: 0x3fffffff 1073741823
31: 0x7fffffff 2147483647
32: 0xffffffff 4294967295