abs函数的实现
abs函数即取一个整形数的绝对值,今天在IDA查看cygwin的实现时候发现其实现过程,这里总结三种情况(感觉这类型东西也很适合用于笔试或面试):
(1)带if分支的利用补码特性:
正数的补码和原码相同;负数的补码是:补码=~(其正数的)原码+1。因此如果是负数求绝对值可以:(绝对值)原码=~(补码-1)
int _abs(signed int i)
{
if (i<0)
return ~(--i);
return i;
}
(2)带if分支(判断分支)的传统想法:
这就很接近一般人想法了,正数保持原样,负数取反
int _abs(singed int p)
{
return p>0?p:-p;
}
(3)不带if分支(判断分支)的位运算:
我是从cygwin中逆向得到的代码
int __cdecl _abs(signed int i)
{
return ((i >> 31) ^ i) - (i >> 31);
}
负数肯定第一位是1,右移31位后是0xFFFFFFFF,-1与原值异或即是求反,减去-1即是加一:~补码 - (-1)=(其正数的)原码
正数则第一位是1,右移31位后是0x00000000,0与原值异或即是保持原值,正数还是以前这么多的值