【问题标题】:Confused understanding a passage about char and int types from K&R's "The C Programming Language" [duplicate]混淆理解 K&R 的“The C Programming Language”中关于 char 和 int 类型的段落 [重复]
【发布时间】:2013-12-30 15:43:43
【问题描述】:

关于第 1 章中的这段话:Kernighan 和 Ritchie 的教程介绍:C 编程语言(我已将需要澄清的具体部分加粗,并在下面详细说明):

使用 getchar 和 putchar,您可以编写大量有用的代码,而无需了解更多有关输入和输出的信息。最简单的示例是一个程序,它一次将其输入复制到其输出一个字符: 读一个字符 while(字符不是文件结束指示符) 输出刚刚读取的字符 读取一个字符 将其转换为 C 给出:

#include <stdio.h>
/* copy input to output; 1st version */ main()
{
       int c;
       c = getchar();
       while (c != EOF) {
           putchar(c);
           c = getchar();
       }
}

关系运算符 != 表示“不等于”。 当然,在键盘或屏幕上看起来是一个字符,就像其他所有东西一样,在内部存储为位模式。 char 类型专门用于存储此类字符数据,但可以使用任何整数类型。我们使用 int 是出于一个微妙但重要的原因。

问题在于将输入的结尾与有效数据区分开来。解决方案是当没有更多输入时,getchar 返回一个独特的值,该值不能与任何真实字符混淆。这个值称为 EOF,表示“文件结束”。我们必须将 c 声明为一个大到足以容纳 getchar 返回的任何值的类型。我们不能使用 char,因为除了任何可能的 char 之外,c 必须足够大以容纳 EOF。因此我们使用 int。

我的理解是 Char 是 Int 的一种类型,只是它更小(就像其他语言中的 Int16、Int32、Int64 一样,但可以表示数字的大小)。

我知道每个字符都可以用一个 Char 类型的整数来表示,那么为什么 EOF 值不能用 Char 来表示呢?是不是因为 Char 类型中的每一个整数都已被计算在内,而对于数据类型来说,再多一个数字也太大了?

对我的知识的任何解释或更正将不胜感激。

【问题讨论】:

  • FWIW,K&R 不是一本从 21 世纪学习 C 的好书。它充满了神秘的单行代码而不是可维护的代码,以及不推荐使用的东西,比如没有原型的函数(例如你引用的例子。)
  • @OliCharlesworth 你会推荐什么书/网站?
  • @OliCharlesworth 您所说的 K&R 是否适用于两个版本,还是仅适用于第一个版本?
  • @DennisMeng:不确定,TBH。

标签: c types kernighan-and-ritchie


【解决方案1】:

是不是因为 Char 类型中的每一个整数都已经被计算在内,而对于数据类型来说,再多一个数字也太大了?

是的,完全正确。更具体地说,整个想法是将EOF 定义为一个可以与getchar 可能从文件中检索到的任何值区分开来的值。由于您可以将char 的任何可能值写入文件,因此您也可以从文件中读取char 的任何可能值。要让EOF 正确完成其工作,它必须不同于任何可能已写入/读取文件的值。为此,它必须是一个不适合 char 的值。

【讨论】:

  • 所以如果一个普通的 Int 是 32 位,2^32,并且一个 Char 是相同的类型,除了 8 位版本:2^8 = 256,这是否意味着 0 到 256 的每个数字代表一个字符,并且没有更多/少于那些?而且它之所以称为 Char 类型,是因为它代表字符,并且可以很容易地称为 Int8 吗?我只是想确保我正确理解了所有这些内容。
  • @nf7:有一个小小的警告,是的。需要注意的是,范围是 0 到 255,而不是 0 到 256。事实上,不少库(例如 Boost,至少一次)定义了 int8_t 类似:typedef char int8_t;
  • 最后一个数字被省略是否有特定原因?最后一个数字是否允许其他数据类型/大小的可接受值?
  • @nf7 256 不能用 8 位表示。二进制格式为100000000
  • @JerryCoffin 还有一个更重要的警告,如果字符集这样说,每个字节只代表一个字符。例如,UTF-8 可以用 2、3 或 4 个字节来表示一个字符。
【解决方案2】:

C 标准确实保证 getchar() 的返回值是有效字符或不同的代码。 EOF,不是有效字符的代码。 EOF 扩展为整数常量表达式,类型为 int,可能为负值。

【讨论】:

    【解决方案3】:

    问题是“C”标准没有指定“char”的符号性。因此,虽然现代实现可能会提供“签名”和“无符号”字符;早期的标准实际上发生了变化(至少两次)。该标准还指定(自 1989 年以来),EOF 具有的任何值;这是负面的。

    【讨论】:

    • @JerryCoffin 你确定吗?它总是在char 的范围之外,但我隐约记得一些实现返回值257(我认为是摩托罗拉MVM Unix)。
    • @JerryCoffin C89ANSI X3.159-1989 §4.9.1 "EOF - 扩展为一个负整数常量表达式,由多个函数返回以指示文件结束,即,不再有来自流的输入;"
    • 我相信 charint 具有相同的范围是合法的,前提是实现不允许文件包含代表 EOF 的 char 值。在此类实现中,必须对 char 进行签名,以确保每个 char 都可以表示为 int
    【解决方案4】:

    EOF 真正的意思是没有字符,因此它不能是一个普通字符。虽然可以选择从char 的范围中挑选出一个值来标记这个特定的值,但是拥有一个超出范围的值允许在char 为8 位的任何平台中管理256 个唯一有效的字符。为了能够保存超出范围的值,该函数必须使用整数类型,该类型可以表示char 中的所有值以及至少一个以上。

    【讨论】:

      【解决方案5】:

      char 类型可以是有符号的或无符号的,具体取决于实现,但 EOF 通常定义为 -1。如果char 是无符号的,则它不能表示-1 的值,因此getchar() 被定义为返回一个int,它在无限制时总是有符号的,因此可以表示char 的所有可能值代表-1(EOF)。

      分享和享受。

      【讨论】:

        【解决方案6】:

        我的理解是 Char 是 Int 的一种类型,只是它更小

        是的。

        我知道每个字符都可以用一个 Char 类型的整数来表示,那么为什么 EOF 值不能用 Char 来表示呢?是不是因为 Char 类型中的每一个整数都已被计算在内,而对于数据类型来说,再多一个数字也太大了?

        是的。

        【讨论】:

          【解决方案7】:

          如果您查看 getchar 的手册页,您可以阅读,

          getchar() 等价于 getc(stdin)

          getc() 等价于 fgetc() 不同之处在于它可以实现为 一个多次计算流的宏。

          fgetc() 从流中读取下一个字符并将其返回为 将 unsigned char 强制转换为 int,或文件末尾的 EOF 或错误。

          提纲提要

          SYNOPSIS
             #include <stdio.h>
          
             int fgetc(FILE *stream);
          

          因此 c 应该声明为 int。

          【讨论】:

            【解决方案8】:
            1. 通过使 EOF 超出可能的字符范围,示例代码将成功复制任何(“二进制”)数据。 EOF 不可能是数据中间的有效值。

            2. 最好的 C 语言书籍是 Harbison 和 Steele,C: A Reference Manual。而且我都用过。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-04-05
              • 2010-11-23
              • 1970-01-01
              • 2018-08-19
              • 2017-02-11
              • 2017-12-06
              • 2021-09-19
              • 2023-02-11
              相关资源
              最近更新 更多