一个`char`类型的变量始终都会有8位吗?

68

我一直认为:

  1. char 由一个字节表示,
  2. 一个字节始终有8位,
  3. sizeof(char) 始终为 1
  4. 我可以分配的最大理论内存量(以 char 计)是 RAM 的字节数(加上交换空间)。

但现在我已经阅读了 Wikipedia 上的字节条目,我不再那么确定了。

我的哪些假设是错误的?哪些是危险的?


https://dev59.com/bVLTa4cB1Zd3GeqPXiTE https://dev59.com/-HNA5IYBdhLWcg3wpfiu - Josh Lee
2
@MrLister:其他编程语言与此有何关系? - Ed S.
这些都是char类型,问题非常迫切,以至于我感到有必要提及sizeof char不为1的情况(即使它在C之外。请注意,问题标题和问题文本都没有提到C)。 - Mr Lister
4
@MrLister:这就是我们有标签的原因。 - user195488
CHAR_BIT是否会大于8?,系统中1个字节不等于8个位?,哪些平台具有不同于8位字符的东西? - phuclv
这个回答解决了你的问题吗?是否存在sizeof(char) != 1或者至少CHAR_BIT > 8的机器? - phuclv
7个回答

60
  1. 是的,charbyte几乎相同。Byte是最小的可寻址内存量,C中的char也是如此。char的大小始终为1。

    从规范的第3.6节byte中可以看到:

    byte

    可寻址的数据存储单元,足以容纳执行环境中基本字符集中的任何成员

    还有第3.7.1节character:

    character

    单字节字符
    <C>适合于一个字节的位表示

  2. char具有CHAR_BIT位。它可以是任何数字(根据规范,至少为8),但通常最常用的是8位。然而,真正的机器有16位和32位的char类型。CHAR_BITlimits.h中定义。

    从规范的第5.2.4.2.1节整数类型的大小<limits.h>中可以看到:

    下面给出的值将被可用于

    #if
    预处理指令的适当常量表达式所取代。而且,除了CHAR_BITMB_LEN_MAX之外,以下将被替换为具有与转换为整数提升后对应类型的对象相同类型的表达式。它们的实现定义值的绝对值(magnitude)将等于或大于(绝对值)所示的值,并具有相同的符号。

    ——不是位域的最小对象的位数(字节)

    CHAR_BIT                 8

sizeof(char) == 1。始终如此。 从规范的第6.5.3.4节 sizeof操作符,第3段:

当应用于具有类型的操作数charunsigned charsigned char(或其限定版本)时,结果为1。

您可以分配尽可能多的内存 - 标准中没有定义可以分配多少内存。例如,您可以想象一个带有云存储支持的内存分配系统的计算机 - 您可以分配的内存实际上可能是无限的。

这里是完整的规范部分7.20.3.3函数malloc:

概要

1 #include <stdlib.h>
   void *malloc(size_t size);

描述

2 malloc函数分配一个大小由size指定且值不确定的对象的空间。

返回

3 malloc函数返回null指针或指向分配空间的指针。

这就是整个规范,因此你实际上没有任何可以依赖的限制。


3
具体而言,在Linux上启用内存超额分配后,完全可以在一台只有8G物理内存和交换空间的计算机上分配2TB内存。 - Dave
1
@J.F.Sebastian,这正是我回答的第一部分所说的。 - Carl Norum
@CarlNorum:我在你的答案的第一部分中没有看到“CHAR_BIT”的提到。你是否声称从sizeof(char)==1(true)可以得出类型char中位数为CHAR_BIT,即没有填充位?无论答案如何,请重新开放我的问题,因为你的答案对于我来说至少没有回答我的问题 -- 这些问题是相关的,但我没有看到答案中的联系。 - jfs
1
@CarlNorum:byte == char不是精确的,即它是错误的。(无关:我在你的答案中没有看到“最小”的字眼)。在许多情况下,它们可以互换使用(我同意“几乎相同”),但它们并不完全相同(正如您自己答案中的C标准引用所明确说明的那样)。char是一种类型。字节是一种存储单元。字符适合一个字节。恰好发生所有CHAR_BIT位都被char类型使用(没有填充位),因此“一个字符有CHAR_BIT位。”是正确的,但这并不是从第1部分得出的。 - jfs
我的回答中有很多规范引用,涵盖了你所有的疑虑。而且,在C语言中,“byte”和“char”是可以互换使用的。 - Carl Norum
显示剩余2条评论

17

sizeof(char) 始终为 1 字节。然而,一个字节不总是一个八位组:例如,德州仪器 TI C55x 是一种带有 16 位字节的 DSP。


5
有很多真实的机器使用非8位字节。 - Carl Norum
1
他的问题的答案很简单,就是“NO”。这正是为什么在POSIX库中存在CHAR_BIT常量的原因。 - Tomas Pruzina
@TomasPruzina 在这里提到POSIX(而不是ISO C)可能有点误导,因为早在POSIX-2001 / SUSv3等标准中就要求CHAR_BIT = 8(尽管POSIX.1-1988、SUSv1和SUSv2仅重复了ISO C的要求,即CHAR_BIT≥8)。据我所知,大多数具有非8位字符的系统明显不符合POSIX标准。 - Alex Shpilkin

11

sizeof(char) 被定义为始终等于 1。来自 C99 标准:

当应用于类型为 char、unsigned char 或 signed char(或其限定版本)的操作数时,结果为 1。

然而,并不保证它是8位。实际上,在绝大多数平台上都是这样,但从技术角度来说不能保证总是这种情况(也不应该过于关心,因为您应该使用 sizeof)。


你能解释一下这是什么意思吗?A)你说“sizeof(char)被定义为始终为1”,指的是什么?B)你说“但不能保证它是8位”,“它”指的是什么?一个字节?一个字符?C)你建议使用sizeof(char),好像在暗示它可能不是1,所以最好总是使用sizeof。但是你又说“sizeof(char)被定义为始终为1”。那么你是指如果平台不符合C99标准怎么办? - barlop
我想你的意思是A)1字节B)一个字节,因此一个char作为一个字节,不能保证是8位。但“C”呢?如果你使用sizeof(char),那有什么用处呢?即使你知道它总是1,那也不会告诉你它有多少位。 - barlop
1
在任何给定的平台上,“byte”、“char”和用于引用内存中地址或大小的单位是相同的。即使在字节不是8位的系统上,sizeof byte始终为1,因为sizeof的结果是以字节为单位测量的。这很有用,因为在每个平台上,内存都是以字节为单位进行测量和寻址的。字节中的位数由平台定义,因此在编译时已知,并且可以使用#define。 - thomasrutter

6

具体而言,一些架构,特别是在DSP领域,其字符长度超过8位。实际上,它们为了速度而牺牲了内存空间。


3
考虑到我所在的公司提供这样的编译器,我觉得这个downvote相当令人困惑...请解释一下! - Lindydancer

4
在C语言中,char类型始终为1个字节,所以您的第一个和第三个假设是正确的。
然而,一个字节不总是等于8位,因此您的第二个假设并不总是成立。话虽如此,目前存在的99.99%的系统都使用8位字符,因此大量的代码都默认使用8位字符,并且在所有目标平台上都能正常运行。显然,Windows和Mac机器始终使用8位字符,至于Linux,据我所知也是如此(Linux已经移植到了许多平台,我不能100%确定是否有人将Linux移植到某些需要9位字符的平台)。
可分配的最大内存量是虚拟内存的大小减去操作系统保留的空间。

错误。sizeof(char)始终为1,这并不意味着char始终为8位。 - Ed S.
第一个假设:“char由一个字节表示”,第三个假设:“sizeof(char)始终为1。”两者都是正确的,即使在编辑之前,我也没有声称相反。 - Adam Mihalcin
@nos:那绝对不是他说的。他已经编辑了回复以使其正确,但最初并非如此,这就是为什么它有3个踩的原因。 - Ed S.
@EdS。请检查编辑历史记录。第一段没有改变,所以不要声称“他后来编辑了回复”来修正某些错误。 - Adam Mihalcin
@AdamMihalcin:不,不是这样的。您实际上是因为对OP的问题回答“是”而说“它将始终是8位”,因此才会得到负投票。我并不是快速发布不正确的答案然后稍后填写相关信息的大粉丝,但现在它已经正确,我已经取消了我的负投票。 - Ed S.
显示剩余4条评论

4
传统上,一个字节不一定是8位,而只是一个较小的存储区域,通常适合存储一个字符。C标准遵循了这个用法,因此malloc和sizeof使用的字节可以超过8位[注](标准不允许它们少于8位)。
但是sizeof(char)始终为1。
记住C FAQ可以提升职业发展。

3
不幸的是(或者说幸运,这取决于你如何看待事物),人们通常认为一个字节是8位,但这与C编程语言所认定的字节并不相同。从之前的答案可以看出,在C编程语言中,字节有一个确切的定义,而在该定义中没有提到字节是8位。它只是简单地说明一个字节是“可寻址的数据存储单元,足以容纳执行环境的基本字符集中的任何成员”。
因此,回答你的问题,“char是否总是有8位”,答案是,不总是,但大多数情况下它会有8位。如果您想了解您的系统上数据类型消耗了多少位空间,您可以使用以下代码行:
sizeof(type) * CHAR_BIT

其中,type是您的数据类型。例如,要找出在您的系统上一个char占用多少位,您可以使用以下代码:

printf("The number of bits a 'char' has on my system: %zu\n", sizeof(char) * CHAR_BIT);

以下内容摘自GNU C库参考手册,其中对这个主题有如下启发性的解释:

There is no operator in the C language that can give you the number of bits in an integer data type. But you can compute it from the macro CHAR_BIT, defined in the header file limits.h. CHAR_BIT — This is the number of bits in a char—eight, on most systems. The value has type int. You can compute the number of bits in any data type type like this:

    `sizeof (type) * CHAR_BIT` 

That expression includes padding bits as well as value and sign bits.


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