dat*_*ili 86 c bit-manipulation
引用用于计算整数绝对值(abs)的代码而不分支来自http://graphics.stanford.edu/~seander/bithacks.html:
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
r = (v + mask) ^ mask;
Run Code Online (Sandbox Code Playgroud)
专利变化:
r = (v ^ mask) - mask;
Run Code Online (Sandbox Code Playgroud)
CHAR_BIT它是什么以及如何使用它?
Ara*_*raK 209
CHAR_BIT是的位数char.目前,几乎所有架构每字节使用8位,但并非总是如此.一些旧机器曾经有7位字节.
它可以在<limits.h>.
尝试回答CHAR_BIT原始问题中的明确问题(什么是)和隐含问题(这是如何工作的)。
C 和 C++ 中的Achar表示 C 程序可以寻址的最小内存单元*。
CHAR_BIT在 C 和 C++ 中表示 a 中的位数char。由于对 char 类型的其他要求,它必须始终至少为 8。实际上,在所有现代通用计算机上,该值恰好是 8,但某些历史或专业系统可能具有更高的值。
Java 没有CHAR_BITor的等价物sizeof,也不需要它,因为 Java 中的所有基本类型都是固定大小的,并且对象的内部结构对程序员来说是不透明的。如果将此代码翻译为 Java,您可以简单地替换sizeof(int) * CHAR_BIT - 1为固定值 31。
在此特定代码中,它用于计算 中的位数int。请注意,此计算假设该int类型不包含任何填充位。
假设您的编译器选择对有符号数字的位移位进行符号扩展,并假设您的系统对负数使用 2 补码表示,这意味着mask正值或零值将为 0,负值将为 -1。
要对二进制补码取反,我们需要执行按位非运算,然后加一。同样,我们可以减一,然后按位求反。
再次假设二进制补码表示法 -1 由全 1 表示,因此异或与 -1 等效于按位求反。
因此,当 v 为零时,该数字保持不变,当 v 为 1 时,该数字被取反。
需要注意的是,C 和 C++ 中的有符号溢出是未定义的行为。因此,abs在最负值上使用此实现会导致未定义的行为。可以通过添加强制转换来修复此问题,以便以 unsigned int 计算程序的最后一行。
* 通常但不一定与硬件可以寻址的最小内存单元相同。一种实现可以潜在地将多个硬件可寻址存储器单元组合成一个程序可寻址存储器单元,或者将一个硬件可寻址存储器单元分割成多个程序可寻址存储器单元。
您应该知道,此代码取决于有符号类型上右移位的实现定义行为。gcc 承诺始终提供合理的行为(符号位扩展),但 ISO C 允许实现对高位进行零填充。
解决这个问题的一种方法是:
#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif
Run Code Online (Sandbox Code Playgroud)
您的Makefile等config.h可以HAVE_SIGN_EXTENDING_BITSHIFT根据您的平台在构建时定义。