更好的 CHAR_BIT 名称是什么?

18

我刚刚在查看一个答案时发现,即使在较新的GCC版本中,CHAR_BIT也没像我预期的那样被头文件定义,甚至没被#include <bitset>定义。

我真的必须要#include <climits>才能得到CHAR_BIT的“功能”吗?


16
包括climitslimits.h有什么问题? - Michael Burr
4
避免写入神奇数字8似乎会带来很多麻烦(并可能增加编译时间),这看起来只是个小问题。 - Potatoswatter
等等,你是在问获取CHAR_BIT表示的信息的不同方法吗?这比我最初的理解更有意义。 - Dennis Zickefoose
16
尝试测量包含它和不包含它之间的差异,我打赌你几乎察觉不到任何区别。请记住,“那些愿意为性能而牺牲正确性的人既得不到正确性也得不到性能”。而且我们谈论的是编译时间,甚至还没有运行时。 - David Rodríguez - dribeas
@Dennis:是的,虽然如果另一个常用头文件包含了<climits>,我会更加高兴。 - Potatoswatter
@David:没错,但是询问一下是否存在无需牺牲的解决方案似乎是值得的。毕竟,CHAR_BIT本身就是一个hackish宏。 - Potatoswatter
6个回答

25

正如你所知,是否包含其他头文件的实现是未指定的。这是被允许的,但不是强制性的。(第17.4.4.1节)因此,你要么必须是明确的,要么必须知道你的保证。

唯一需要C++头文件必须包含另一个文件是如果它需要在另一个文件中有定义。例如,<bitset>需要包含<cstddef>以获取std::size_t,因为标准中明确规定了这一点。(对于这个例子,参见第23.3.5节)

举个反例,考虑<limits>。它可能包括<climits>并使用其中的宏定义numeric_limits的值,并且通常情况下,这是实现最简单的方法。但标准只说这样的话:“与CHAR_MINSHRT_MINFLT_MINDBL_MIN相当”,但没有说它必须按照这些来实现,这意味着<climits>不必被包含。

因此,你唯一可以保证定义了CHAR_BIT的方法是包含<climits>或其他明确规定必须包含它的头文件。就我所知,没有一个头文件必须这样做;实现可以自由地在需要的任何地方硬编码该值,或者包括<limits>并使用std::numeric_limits<unsigned char>::digits(相当于)。


3
你甚至在标题中回答了问题,并提供了一个更好的名称! - Potatoswatter
4
大多数不重要的琐事:请注意,仅适用于C++,包括其他标准头文件的实现是允许的。在C语言中,只有当包括“limits.h”时,编译器实现才能定义CHAR_BIT。实际上,如果用户没有包含limits.h,那么根据C标准,用户完全可以为自己的使用定义CHAR_BIT - 只有在包括limits.h时才保留该标识符。并不是说我主张这是一个好主意,但就C标准而言,这是可以的。 - Michael Burr
8
重要细节:numeric_limits<char>::digits 只有当 char 是无符号类型时才等同于 CHAR_BIT。如果 char 是有符号类型,则它等同于 (CHAR_BIT - 1),因为 digits 成员不计算符号位。建议直接添加 #include <limits.h> 头文件来获取所需的数字。 - Michael Burr
@Michael:你也可以像等价的答案中那样使用“unsigned char”。 - GManNickG
1
@GMan:我想特别提醒你要注意使用unsigned char而不仅仅是char - Michael Burr
1
@Michael:啊,明白了。 :) 也可以做 numeric_limits<char>::digits + numeric_limits<char>::is_signed,但是无所谓。 - GManNickG

9

除非你是为DSP编程,否则更好的名称是8。 POSIX和Windows都要求CHAR_BIT==8,这几乎涵盖了所有有趣的目标,除了DSP。 (我不认为1970年代的大型机仍然是一个有趣的目标,但也许有人会有不同看法...)


2
没错,但在计算std::bitset大小的可能复杂公式中,我会像避开瘟疫一样避免使用字面数字。 - Potatoswatter

6

<climits> 是 C++ 标准规定 CHAR_BIT 所在的地方。即使你可能会在 <bitset> 中找到它,也不保证一定会有,所以最好直接去源头找。包含 <climits> 没有任何问题。


3

定义“新版本”。一个随机的Linux系统给我这些结果:

~> gcc --version
gcc (GCC) 4.1.2 (Gentoo 4.1.2)
[snip]
~> grep CHAR_BIT /usr/include/*.h /usr/include/limits.h:# define CHAR_BIT 8

这不符合条件吗?在C语言中,我认为只需要包含limits.h就足以获得CHAR_BIT(参见此处)


0
我在我的.profile文件中保留了以下函数,用于检查编译器定义的常量。在我的系统中,__CHAR_BIT__已经存在,这意味着如果您可以使用双下划线形式(可能仅适用于gcc),则无需头文件即可使用。
defines () 
{ 
    touch /tmp/defines.h;
    cpp -dD "$@" /tmp/defines.h | awk '$1!="#"{COUNT+=1;print;}END{printf("count %d\n",COUNT);}' | sort;
    rm /tmp/defines.h
}

7
所以你有一个特定于平台的解决方法,可以避免包含只是为了避免对平台做出假设而需要的头文件吗? - jalf
它回答了这个问题。gcc是一个平台吗? - drawnonward

0

是的,你应该 #include <limits.h> 来获取 CHAR_BIT 的定义。这对你的程序来说不是瓶颈(请参见下面的注释),而且在以后你可能会发现需要将程序移植到不同的平台上。并非每个实现都具有8的值。


1
这对你的程序来说根本不是瓶颈,因为它是一个几乎总是扩展为常量的宏。所有的"工作"都在编译时发生。 - Chris Lutz
是的,我知道。现在已经修正措辞了。谢谢。 - Xavier Ho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接