在使用按位操作进行编程时,我有一个疑问。也就是说,在我的项目中,在某个时间点,我需要像这样设置位,如果我输入'1‘,它意味着第一位被设置。如果我输入'2‘,它意味着前2位已设置。
所以,
1-1 2-11 3-111 4-1111
同样,它也是如此。
现在,我需要在一行中编写这种格式的逐位操作。
任何帮助都是非常感谢的。
发布于 2014-08-28 18:53:34
到目前为止,我们已经有了“两个主要的答案”,你通常会得到这个问题。它们的边缘条件是不同的。假设32位无符号整数取公共值,(1u<<n)-1
答案可以处理0到31,0xFFFFFFFF>>(32-n)
答案可以处理1到32。
然后经常会出现的一个问题是,我们可以从0到32吗?
你可以,但很自然地,它会更复杂,特别是如果你不接受条件句的话。通过将这两种方法中的任何一种与三元运算符相结合,很容易实现完整的范围,但如果不这样做,仍然有方法可用。
请注意,n=32
是在n
中设置位0b00100000
的唯一情况。
因此,我们可以做的一件事是提取该位,反转它,并将其向左移位(注意不要执行未定义的移位),如下所示:
((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
发布于 2014-08-28 14:15:09
1 << n
提供了2 ^ n
,因此您可能需要在2 ^ n - 1
中使用以下代码
static inline unsigned int test(int n)
{
return (1u << n) - 1;
}
发布于 2014-08-28 14:16:07
使用无符号整型(假设是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;
}
该程序的输出显示,每个后续的位数都会在右侧增加一个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
https://stackoverflow.com/questions/25541858
复制相似问题