以下两个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
? 最佳答案
1a。表达式x & -x
是一个众所周知的“位hack”:它的值等于除一位以外的所有位均设置为0
的值:原始值1
中的最低x
位。 (当然,除非x
是0
。)
例如,在无符号算术中:5 & -5 = 1
,4 & -4 = 4
等。
2a。这立即告诉我们f
的功能:通过使用|
运算符,它将1
和A
中的所有B
位组合在一起,然后在组合值中找到最低的1
。换句话说,f
的结果是一个单词,该单词在1
或1
的最低A
位置中包含唯一的B
位。
1b。表达式(x + 1) & ~x
是一个众所周知的“位hack”:它计算设置为0
的所有位,除了0
原始值中的最低x
位。在结果值中,0
中的最低x
位变为唯一的1
。 (当然,除非x
为全1位。)
例如,在无符号算术中:(5 + 1) & -5 = 2
,(4 + 1) & -4 = 1
等。
2b。表达式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。
我有一种直觉的感觉(可能是错误的),为了通过对现有表达式应用附加操作来将一个函数正式转换为另一个函数,一个函数至少需要其中一个函数是“可逆的”(有些该术语的半非正式含义)。这两个对我来说看起来都不足够“可逆”。
关于c - 等效于两个按位运算,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25279002/