以下两个C函数是等效的:
unsigned f(unsigned A, unsigned B) {
return (A | B) & -(A | B);
}
unsigned g(unsigned A, unsigned B) {
unsigned C = (A - 1) & (B - 1);
return (C + 1) & ~C;
}
我的问题是:为什么它们相同? g
将哪些规则/转换转换为f
?
答案 0 :(得分:7)
<强> 1A 即可。表达式x & -x
是一个众所周知的&#34; bit hack&#34;它评估为一个值,所有位都设置为0
,除了一位:最低1
位在x
的原始值中。 (当然,除非x
为0
。)
例如,在无符号算术中:5 & -5 = 1
,4 & -4 = 4
等。
<强> 2A 即可。这会立即告诉我们f
函数的作用:通过使用|
运算符,它会合并1
和A
中的所有B
位,然后找到最低1
在组合值中。换句话说,f
的结果是在1
或1
中最低A
位置包含唯一B
位的字词。< / p>
<强>图1b 即可。表达式(x + 1) & ~x
是一个众所周知的&#34; bit hack&#34;它评估为设置为0
的所有位,除了{{{}的原始值中的最低0
位。 1}}。 x
中的最低0
位成为结果值中唯一的x
。 (当然,除非1
全是1位。)
例如,在无符号算术中:x
,(5 + 1) & -5 = 2
等。
<强> 2B 即可。表达式(4 + 1) & -4 = 1
将x - 1
中的所有尾随0
位替换为x
,并将1
中的1
替换为x
,并保留0
x
的其余部分没有变化。运算符&
组合了所有0
位(就像运算符|
组合了所有1
位)。这意味着(A - 1) & (B - 1)
的最低0
位将位于1
或A
中最低的B
位。
<强> 3B 即可。每1b,(C + 1) & ~C
将最低0
替换为孤独1
,将其他所有内容归零。
这意味着g
与f
的功能相同。两个函数都查找并返回两个输入值之间的最低1
位。结果总是2的幂(或只是0)。例如。如果至少有一个输入值是奇数,则结果为1.
我有一种直觉(可能是错误的),为了通过对现有表达式应用附加操作来构建一个函数到另一个函数的正式转换,需要至少其中一个函数为#34可逆&#34; (是该术语的一些半非正式含义)。这两者中的任何一个都看起来不够充分&#34;可逆&#34;给我......