我正在阅读 "The C Programming Language" (2ed),但我不明白一个概念:

I am reading "The C Programming Language" (2ed) and I didn't understand a concept:

我正在阅读“The C programming Language”(第 2 版),但我没有理解一个概念。

有这段代码可以将输入复制到输出

#include <stdio.h>

main()
{
    int c;
    c = getchar();
    while (c != EOF) {
        putchar(c);
        c = getchar();
    }
}

一开始,c 被声明为 int 类型变量,但如果我写类似“test line”的内容,输出就是预期的“test line”。我的问题是:如何将 c 声明为 int 类型变量,但程序存储 space 足以存储大量字符?在计算机“内部”,它注册为字符数组?这个过程是如何运作的?

假设我正在为我的朋友调酒。我面前有四只眼镜。我想在每个玻璃杯中加入 1/8 杯(1 杯)杜松子酒。但我没有 1/8 杯量杯。所以我拿了一个 1/4 杯的量杯,我把它倒了一半,这样我每杯量 1/8 杯酒。

我用1/4杯量器量1/8杯液体有问题吗?顶部的所有空 space 怎么办?好吧,显然,它根本不会造成任何问题。

类似地,如果您使用 int(可能是 16 位或 32 位变量)来保存调用 getchar() 的 return 值,这不会即使从 getchar 返回的大多数字符值只是 8 位,也会导致任何问题。

但是 会在 getchar 到 return 代码 EOF(文件结尾)到你! EOF 是一个 不适合 8 位的值,因为它(根据定义)不是 8 位字符值。这就是为什么使用 int 变量来处理从 getchar 返回的值很重要,而不是 char ,这看起来很明显。

首先,一些背景。

字符是字符串的一个元素。一个字符是一个数字.

您在屏幕上看到的字形(ab 等)就是您的终端解释它接收到的数字(97、98 等)的方式。

在C程序中,完全没有区别

'a'
97

两者都是 int 类型的整数文字,值为九十七。 (我在这里假设基于 ASCII 的机器。它们在基于 EBCDIC 的机器上实际上是不同的。)


现在回答你的问题。

but the program stores space enough to a lot of characters ?

没有。 c 在任何给定时间只包含一个字符。第一次通过循环时,116 aka 't' 被分配给它。第二次通过循环,101 aka 'e' 被分配给它。等等

how is "c" declared as a int type variabel but the program stores space enough to a lot of characters ?

显示的源代码没有存储很多字符。它一次处理一个字符。

c = getchar(); 将一个输入字符的代码放在 c 中。然后 putchar(c); 将该代码写入输出。然后程序可以忘记这个角色。它不再需要它了,它可以获得一个新的字符代码并为此重新使用 c

输出流在将它们写入输出设备之前可能会在缓冲区中保存很多字符,但这是在单独的源代码中,而不是直接在显示的源代码中。它是 C 标准库的一部分。

but if i write something like "test line" the output is the expected "test line".

how is "c" declared as a int type variabel but the program stores space enough to a lot of characters ?

所有输入并没有同时存储在变量 c 中,而是存储在输入和输出缓冲区中。变量 c 一次处理一个字符。

让我们来看看事件的顺序。

  1. main() 开始并运行到 getchar().

  2. getchar() 等待输入。

  3. 用户输入t,OS缓冲字符。

  4. 用户类型 e s ...., e OS 缓冲这些字符。

  5. 用户键入输入,OS缓冲字符'\n'并将缓冲区交给stdin for getchar()开始使用。

  6. getchar() returns t 并保存在 c.

  7. 代码继续 putchar(c); 并将 t 放入 stdout 缓冲区。

  8. 代码继续 getchar();,returns 缓冲 ​​e 并保存在 c.

  9. 代码继续 putchar(c); 并将 e 放入 stdout 缓冲区。

  10. 8 - 9 次重复 st line

  11. 代码继续 getchar();,returns 缓冲 ​​\n 并保存在 c.

  12. 代码继续到 putchar(c); 并将 \n 放入 stdout 缓冲区。缓冲区现在被刷新到 OS 输出终端。输出现在可见。

  13. 返回第 2 步,直到没有可用的输入。

  • 有些叫做 io buf,其他叫做 return value
  • 具体可以理解为getchar读取chars到io buffer,return一个一个到api user