什么是CHAR_BIT?


Answers:


-1

您应该知道,此代码取决于对符号类型进行右移的实现定义的行为。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

Makefileconfig.h等等可以HAVE_SIGN_EXTENDING_BITSHIFT根据您的平台在构建时进行定义。


120
我不明白这是如何被接受的答案,因为它没有回答问题,尽管它是一个非常有趣的评论。
qdii

15
@毛里斯:有人编辑了问题,并提出了问题标题的子问题。最初的标题确实很糟糕,但是OP的问题是有关引用的位hack代码是如何工作的,并且“它至少没有可移植性,这就是为什么”是一个有用的答案。
R .. GitHub停止帮助ICE

12
啊我懂了。可悲的是,这个问题在Google搜索结果中的“什么是CHAR_BIT?”中显示的很高。,即使这不是原始问题。:(有了您的解释,我知道您为什么要写这个答案,但是对于后代来说,(a)删除您的答案并将其重写为对问题的注释可能更有用,这样@AraK会显示在顶部,或者(二)编辑你的答案,以便它回答了这个问题目前的标题。
林恩

1
由于OP的原始问题和编辑者对其解释的意图不同,因此,似乎原始请求的性质被非自愿地改变了。虽然这两个问题(原始的和已编辑的)都有其优点,但需要解决这一差异。我现在询问:这个答案可以添加到Wiki吗?这可能会帮助正在搜索此类信息的人,尽管它与原始问题无关。之后,可以再次编辑问题,以适应dato datuashvili的原始要求。只是一个有关的读者...

2
我只是看了这个问题的历史,最初的问题实际上并没有在任何地方询问代码是如何工作的。编辑者晋升为标题的问题是其中唯一的实际问题。
洗瓶

224

CHAR_BIT是中的位数char。如今,几乎所有体系结构每字节都使用8位,但并非总是如此。某些较旧的机器曾经有7位字节。

可以在中找到<limits.h>


3
一些DSP具有10个或更多的位字节。
朱里·罗伯

63
CHAR_BIT>=8对于仅具有单一类型大小(通常为32位)的DSP,C要求并允许更大的值。POSIX要求CHAR_BIT==8。通常,您可以假设任何面向多用户/多任务服务器或面向交互使用的体系结构都可以连接到Internet或与外界交换文本数据CHAR_BIT==8
R .. GitHub停止帮助ICE,2010年

6
@caf:不,是C99要求类型int8_t并且uint8_t存在。因此,存在一种宽度为8的类型。因为sizeof任何类型必须与之兼容,sizeof char实际上sizeof int8_t必须为1 CHAR_BIT == 8。我在此处围绕该观察写了一些东西:gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt'7

22
@Jens Gustedt:请引用C99规范的一部分。在精确宽度整数类型中,C99规范指出“这些类型是可选的”。(7.18.1.1/3)但是,需要最小宽度和最快宽度类型。
jamesdlin

3
@jamesdlin&caf:对不起,我把事情搞混了。是的,我所指的要求实际上来自POSIX stdint.h。因此,这是必需的,并且也被标记为ISO C标准的扩展,而没有引用该标准的特定版本。我的错。
詹斯·古斯特

2

尝试同时回答原始问题中的显式问题(什么是CHAR_BIT)和隐式问题(这是如何工作的)。


C和C ++中的char表示C程序可以寻址的最小内存单元*

C和C ++中的CHAR_BIT表示char中的位数。由于对char类型的其他要求,它必须始终至少为8。实际上,在所有现代通用计算机上,它恰好是8,但是某些历史或专业系统可能具有更高的价值。

Java没有CHAR_BIT或sizeof的等效项,因此没有必要,因为Java中的所有原始类型都是固定大小的,并且对象的内部结构对程序员来说是不透明的。如果将此代码转换为Java,则只需将“ sizeof(int)* CHAR_BIT-1”替换为固定值31。

在此特定代码中,它用于计算int中的位数。请注意,此计算假定int类型不包含任何填充位。

假设您的编译器选择对有符号数的位移位进行符号扩展,并且假设您的系统对负数使用2s补码表示,则这意味着“ MASK”对于正值或零值将为0,对于负值将为-1。

要使二进制补码取反,我们需要按位取非,然后加一个。等效地,我们可以减去一个,然后按位取反。

再次假设二进制补码表示-1由全1表示,因此异或与-1等效于按位求反。

因此,当v为零时,该数字将保留,而当v为1时,该数字将被取反。

需要注意的是,C和C ++中的签名溢出是未定义的行为。因此,对最大负值使用此ABS实现会导致不确定的行为。可以通过添加强制转换来解决此问题,以使程序的最后一行以unsigned int形式求值。

*通常与硬件可以寻址的最小内存单元相同,但在本质上并不相同。一种实现方式可能会将多个硬件可寻址存储器单元组合成一个程序可寻址存储器单元,或者将一个硬件可寻址存储器单元拆分成多个可程序编程存储器单元。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.