什么是CHAR_BIT?
从http://graphics.stanford.edu/~seander/bithacks.html引用无分支计算整数绝对值(abs)的代码:
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;
获得专利的变体:
r = (v ^ mask) - mask;
什么是CHAR_BIT
以及如何使用它?
你应该知道这个代码依赖于签名types的正确的bitshift的实现定义的行为。 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
您的Makefile
或config.h
等可以在构build时根据您的平台定义HAVE_SIGN_EXTENDING_BITSHIFT
。
CHAR_BIT
是char
的位数。 目前,几乎所有的体系结构都使用每个字节8位,但事实并非如此。 一些旧的机器曾经有7位字节。
它可以在<limits.h>
find
试图在原始问题中回答明确的问题(什么是CHAR_BIT)和隐含的问题(这是如何工作的)。
C和C ++中的char代表C程序可以处理的最小内存单元*
C和C ++中的CHAR_BIT表示char中的位数。 由于chartypes的其他要求,它必须至less为8。 在所有现代通用计算机的实践中,它恰好是8,但是一些历史或专业系统可能具有更高的价值。
Java没有CHAR_BIT或sizeof的等价性,不需要它,因为Java中的所有基本types都是固定大小的,而对象的内部结构对于程序员是不透明的。 如果将这个代码翻译成Java,你可以简单的用固定值31replace“sizeof(int)* CHAR_BIT – 1”。
在这个特定的代码中,它被用来计算int中的位数。 请注意,此计算假定inttypes不包含任何填充位。
假设你的编译器select在有符号数的位移上签名扩展,并且假设你的系统对负数使用二进制补码表示,这意味着“MASK”对于正值或零值将是0,对于负值是-1。
为了否定二进制补码,我们需要执行一个按位不是,然后添加一个。 我们可以等于减去一个,然后逐位否定它。
再次假设二进制补码表示-1由全1表示,因此排他或与-1等于按位否定。
所以当v是零时,数字是孤立的,当v是1时,它是否定的。
需要注意的是C和C ++中的有符号溢出是未定义的行为。 所以使用这个最实惠的ABS实现会导致未定义的行为。 这可以通过添加转换来修复,以便程序的最后一行在unsigned int中进行计算。
*这通常与硬件可以解决的最小内存单元并不相同。 一个实现可以将多个单元的硬件可寻址存储器组合成一个单元的程序可寻址存储器,或者将一个硬件可寻址存储器单元分成多个可编程存储器单元。