一些有用的位操作技巧。主要来自 Bit Twiddling Hacks
# 符号操作
# 获取整数的符号
对于整数 v
, 其符号 sign
可以用如下方式计算:
int v; // we want to find the sign of v | |
int sign; // the result goes here | |
// CHAR_BIT is the number of bits per byte (normally 8). | |
sign = -(v < 0); // if v < 0 then -1, else 0. | |
// or, to avoid branching on CPUs with flag registers (IA32): | |
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); | |
// or, for one less instruction (but not portable): | |
sign = v >> (sizeof(int) * CHAR_BIT - 1); |
如果希望结果 sign
为 1
或 -1
, 那么可以采用:
sign = +1|(v>>(sizeof(int) * CHAR_BIT - 1)); // if v<0 then -1, else 1 |
如果希望结果为 -1
, 0
或 1
, 那么可以采用:
符号 = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); | |
sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1)); //-1、0 or +1, 速度高,可移植性差 | |
sign = (v > 0) - (v < 0); //-1、0 or +1, 简洁 |
若希望得知非负性,即结果为 +1
或 0
, 那么可以采用:
sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)) |
上述所有的符号判断操作,底层都是基于数字符号位的获取。
# 检测两个整数是否符号相反
希望检测两整数读好相反,可以采用下述代码。其当且仅当符号相反时 bool f = true
, 否则为 false
.
int x, y; // input | |
bool f = ((x ^ y) < 0); |
# 值计算
# 绝对值
如果希望得到整数 v
的绝对值,那么可以采用
int v; // input | |
unsigned int r; // result | |
int const mask = v>>sizeof(int)*CHAR_BIT - 1; | |
r = (v + mask)^mask; |
# 值交换
借助加减法的值交换
#define SWAP(a,b) ((&(a)==&(b)) || \((a)-=(b),((b)+=(a)), ((a)=(b)-(a)))) |
# lowbit
#define LOWBIT(x) ((x)&(-(x))) |