【问题标题】:Will a `char` always-always-always have 8 bits?'char' 总是总是有 8 位吗?
【发布时间】:2012-04-01 10:01:19
【问题描述】:

我一直认为:

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

但现在我已经阅读了Wikipedia entry on the byte,我不再那么确定了。

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

【问题讨论】:

标签: c memory


【解决方案1】:
  1. 是的,charbyte 几乎相同。一个字节是最小的可寻址内存量,C 中的 char 也是如此。char 的大小始终为 1。

    根据规范,3.6 字节部分:

    字节

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

    以及3.7.1 部分字符

    角色

    单字节字符
    适合一个字节的位表示

  2. charCHAR_BIT 位。它可以是任何数字(嗯,根据规范,8 或更大),但绝对是最常见的 8。不过,有 16 位和 32 位 char 类型的真实机器。 CHAR_BITlimits.h 中定义。

    根据规范,5.2.4.2.1 整数类型的大小<limits.h> 部分:

    下面给出的值应替换为适合在 #if 预处理指令中使用的常量表达式。此外,除了 CHAR_BITMB_LEN_MAX 之外,以下内容应替换为与作为相应类型的对象的表达式具有相同类型的表达式根据整数促销转换。它们的实现定义值的大小(绝对值)应等于或大于所示值,符号相同。

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

  3. sizeof(char) == 1。总是。

    根据规范,6.5.3.4 sizeof 运算符部分,第 3 段:

    当应用于类型为 charunsigned charsigned char 的操作数(或合格版本)时其中)结果为1。

  4. 您可以分配尽可能多的内存,只要您的系统允许您分配 - 标准中没有定义可能的内存量。例如,您可以想象一台具有云存储支持的内存分配系统的计算机——您的可分配内存实际上可能是无限的。

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

    概要

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

    说明

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

    退货

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

    这就是规范的全部内容,因此实际上没有任何可以依赖的限制。

【讨论】:

【解决方案2】:

sizeof(char) 始终为 1 个字节。然而,一个字节并不总是一个八位字节:例如,Texas Instruments TI C55x 是一个 16 位字节的 DSP。

【讨论】:

  • 非8位字节的真机很多。
  • 他的问题的答案很简单,不。这正是 posix 库中存在 CHAR_BIT 常量的原因。
  • @TomasPruzina 在这里提到 POSIX(而不是 ISO C)可能有点误导,因为早在 POSIX-2001 / SUSv3 的标准要求 CHAR_BIT = 8(尽管 POSIX.1-1988、SUSv1 和SUSv2 仅重复了 CHAR_BIT ≥ 8 的 ISO C 要求)。 AFAIU 大多数具有非 8 位字符的系统绝对是非 POSIX。
【解决方案3】:

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?
  • 我想你的意思是 A)1 字节 B)一个字节,因此一个 char,因为一个 char 是一个字节,不能保证是 8 位。但是“C”呢?如果你使用 sizeof(char) 如果你知道它永远是 1 那有什么用呢?而且那个 1 无论如何也不会告诉你它有多少位。
  • 在任何给定的平台上,“字节”、“字符”和用于引用内存中地址或大小的单位都是相同的。即使在字节不是 8 位的系统上,sizeof 字节也始终为 1,因为 sizeof 的结果以以字节为单位来衡量。这很有用,因为在每个平台上都是测量和寻址内存的方式。字节中的位数由平台定义,因此在编译时已知,您可以使用#define
【解决方案4】:

具体来说,一些架构,尤其是在 DSP 领域,char:s 大于 8 位。实际上,它们会牺牲内存空间来换取速度。

【讨论】:

  • 鉴于我在一家提供此类编译器的公司工作,我发现投反对票相当令人费解……请解释一下!
【解决方案5】:

传统上,一个字节不一定是 8 位,而只是一个很小的 内存区域,通常适合存储一个字符。 C 标准遵循这种用法,所以 malloc 和 sizeof 使用的字节数 可以超过 8 位。 [脚注](标准不允许他们 减少。)

但 sizeof(char) 始终为 1。

记住C FAQ 是一项提升职业生涯的举措。

【讨论】:

    【解决方案6】:

    不幸的是(或者可能是幸运的,取决于您如何看待事物)是,通常认为字节(8 位)的概念与 C 编程语言认为字节的含义不同。查看前面的一些答案,当涉及到 C 编程语言时,一个字节有一个确切的定义,并且在定义中没有任何地方提到一个字节是 8 位。它只是提到一个字节是

    “一个可寻址的数据存储单元,大到足以容纳任何成员 执行环境的基本字符集。”

    因此,要回答“char always-always-always-always 是否有 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 库参考手册,其中包含有关此主题的以下说明性说明:

    C 语言中没有运算符可以告诉你 整数数据类型中的位。但是你可以从宏中计算出来 CHAR_BIT,在头文件limits.h中定义。 CHAR_BIT — 这是 一个字符中的位数——在大多数系统上是八位。该值具有类型 诠释。您可以计算任何数据类型的位数,例如 这个:

        `sizeof (type) * CHAR_BIT` 
    

    该表达式包括填充位以及值和符号位。

    【讨论】:

      【解决方案7】:

      在 C 中,char 始终是一个字节,因此您的第一个和第三个假设是正确的。

      一个字节总是8位,所以你的第二个假设并不总是成立。也就是说,当今存在的所有系统中 >= 99.99% 具有 8 位字符,因此许多代码隐含地假定为 8 位字符,并且在所有目标平台上都可以正常运行。当然,Windows 和 Mac 机器总是使用 8 位字符,AFAIK Linux 也是如此(Linux 已经移植到很多平台,我不能 100% 确定有人没有将 Linux 移植到 9 位字符的平台有道理)。

      可以分配的最大内存量是虚拟内存的大小减去为操作系统保留的空间。

      【讨论】:

      • 错了。 sizeof(char) 始终为 1,这并不意味着 char 始终为 8 位。
      • 第一个假设:“一个 char 由一个字节表示”,第三个假设:“sizeof (char) 始终为 1。”两者都是正确的,甚至在编辑之前我也没有声明。
      • @nos:他绝对不是这么说的。此后,他将回复编辑为正确,但最初并非如此,这就是为什么它有 3 个反对票。
      • @EdS。检查编辑历史。第一段没有改变,所以不要声称“他已经编辑了回复”来纠正一些错误。
      • @AdamMihalcin:不,不是。您基本上说“是的,它将始终是 8 位”,因为您对 OP 的问题说“是”。这就是你得到反对票的原因。我不喜欢快速发布错误答案,只是为了稍后填写相关信息,但我已经删除了我的反对票,因为它现在是正确的。
      猜你喜欢
      • 2012-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 2012-07-21
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多