从Bit Twiddling Hacks网站考虑this link。 为了计算尾随位,使用以下算法:
unsigned int v; // 32-bit word input to count zero bits on right
unsigned int c = 32; // c will be the number of zero bits on the right
v &= -signed(v); /* THIS LINE */
if (v) c--;
if (v & 0x0000FFFF) c -= 16;
if (v & 0x00FF00FF) c -= 8;
if (v & 0x0F0F0F0F) c -= 4;
if (v & 0x33333333) c -= 2;
if (v & 0x55555555) c -= 1;
有人可以向我解释标记为/* THIS LINE */
的行的作用,更重要的是,是否可以仅使用按位运算来避免使用signed()
?
编辑:如何通过算术/逻辑/按位运算替换signed()
?
答案 0 :(得分:5)
v &= -signed(v)
将清除除v的最低设置位(1
- 位)之外的所有位,即从v中提取最低有效位1(v将随后变为幂为2的数字)。例如,对于v=14 (1110)
,在此之后,我们有v=2 (0010)
。
此处,使用signed()
是因为v是unsigned
并且您正在尝试否定unsigned
值(使用VS2012提供编译错误)(来自JoelRondeau的评论)。或者你会收到这样的警告: warning C4146: unary minus operator applied to unsigned type, result still unsigned
(我的测试)。
答案 1 :(得分:0)
表达式v &= -signed(v)
,是对该数字本身的数字和负数进行AND运算。所以我们在数字和数字的二进制补码表示上执行二进制AND
答案 2 :(得分:0)
按照我从代码中理解的内容: -
AND v及其2的补码: - 将第一个1之后的所有数字从右设置为0
示例: - v = 10101000然后-v = ~v + 1(1的补码加1)= 01010111 + 1 = 01011000
v& -v = 10101000& 01011000 = 00001000
答案 3 :(得分:0)
执行-signed(v)
没有简单的按位操作。加法和减法需要“进位”,对位X的操作可能影响位X + 1。所以,需要算术。
但基本上,一元-x
只是二进制0-x
,所以如果你没有直接否定操作,你可以使用标准算法。
答案 4 :(得分:0)
signed
是导致未定义行为的错误。
可以安全地将其卸下。该代码要求无符号取反的行为... signed
取反可能会或可能不会传递。如果没有该关键字,则行为总是符合预期。
现在,代码仍然不可移植。但是至少它是安全的,并且如果int
是32位,它将可以正常工作。