计算整数的符号
int v; // 我们想要找到v的符号
int sign; // 结果保存在这里
// CHAR_BIT是每个字节的位数(通常为8位)。
sign = -(v < 0); // 如果v < 0,则为-1,否则为0。
// 或者,为了避免在带有标志寄存器的CPU(如IA32)上分支:
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// 或者,为了减少一条指令(但不具有可移植性):
sign = v >> (sizeof(int) * CHAR_BIT - 1);
上面的最后一个表达式等同于对于32位整数,sign = v >> 31。这比明显的方法sign = -(v < 0) 快一次操作。这个技巧的原因是,当有符号整数向右移位时,最左边的位的值被复制到其他位上。最左边的位在值为负时为1,否则为0;所有的1位得到-1。不幸的是,这种行为是与体系结构相关的。
或者,如果你希望结果要么是-1,要么是+1,那么可以使用:
sign = +1 | (v >> (sizeof(int) * CHAR_BIT - 1)); // 如果v < 0,则为-1,否则为+1
另一方面,如果你希望结果要么是-1,要么是0,要么是+1,那么可以使用:
sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// 或者,为了更快但不够可移植:
sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1)); // -1, 0, 或 +1
// 或者,为了可移植性、简洁和(也许)速度:
sign = (v > 0) - (v < 0); // -1, 0, 或 +1
如果你希望知道某物是否为非负数,结果为+1,否则为0,可以使用:
sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)); // 如果v < 0,则为0,否则为1