【问题标题】:Example in Chapter 1, 1.5.1, of The C Programming Language Second edittion K&R, [duplicate]C 编程语言第二版 K&R 的第 1 章 1.5.1 中的示例,[重复]
【发布时间】:2016-12-04 07:25:24
【问题描述】:
int c;

while ((c = getchar()) != EOF)
    putchar(c);

"这个值叫做 EOF,代表“文件结束”。我们必须声明 c 是 一个足够大的类型,除了任何可能的字符外,还可以容纳 EOF。 因此我们使用 int。”

如果我错了,请纠正我:

  • (有符号)字符 = [-128。 +127]
  • 无符号字符 = [0, 255]
  • EOF = -1

当我在上述程序中将int 替换为char 时,它似乎按预期工作,但经过一些研究我发现它不是因为变量c 不能存储-1 又名EOF (尽管使用char)。

我还是运行它并试图让它崩溃,我试图输入负数,如 -1,但它不起作用。我相信这是因为它被解释为 2 个不同的字符 -1。我试过ÿ,这是根据http://ascii-code.com/对应ascii值255的字符, 那么上面的程序(使用char而不是int)会因为什么输入而崩溃?

(仅供参考,我使用的是 64 位 fedora Linux)

【问题讨论】:

  • 你认为它为什么会崩溃?
  • Correct me if i am wrong: - 你错了。交换 signedunsigned 范围。正如奥拉夫所说。
  • SCHAR_MINsigned char 的下限,通常是 -128,而不是 -127。这适用于CHAR_BIT==8 的 2 补码实现。其他值是可能的。普通的char 可以是签名的也可以是未签名的;它与signed charunsigned char 具有相同的范围和表示,但它仍然是一个不同的类型。
  • 你对charunsigned char 的看法是错误的——unsigned char 的可能值是 0 - 255,而(有符号)char 的值可以是 -128 到 127。
  • @KeithThompson:如果我们交换 signedunsigned 范围,这些是最小范围。仍然不确定 OP 的问题是什么。

标签: c char int ascii eof


【解决方案1】:

之前在其他答案中已经解释过了,但有时找到重复比给出答案更难。

普通的char 类型可以是有符号或无符号的。

getchar() 函数返回 EOF 或 ...将该字符作为 unsigned char 转换为 int...(引用 fgetc() 的标准,但它适用于 @987654326 @也是)。

如果你有一个无符号的纯 char 类型,那么赋值将生成一个值 0..255,然后将其提升为 int 以与 EOF 进行比较,因为没有任何值 0..255是否定的,测试将始终失败——并且循环不会停止,直到您通过其他方式(中断、重新启动等)终止程序。

如果您有带符号的纯 char 类型,则分配将同时处理一个有效字符(通常是 ÿ — U+00FF,带分音符号的拉丁小写字母 Y,如果您使用的是单字节代码集,例如ISO 8859-15) 和 EOF 标记为 EOF,因此循环可能会在某些文件上过早终止。

所以,取决于机器,循环:

char c;

while ((c = getchar()) != EOF)
    ;

可能是无限循环,也可能在某些数据文件的 EOF 之前终止。两者都不是正确的行为——而且这两种行为都不是崩溃。 (问题中的代码不会崩溃。)将c 的类型更改为int 可以可靠且可移植地修复这两个问题。

请注意,如果您使用的是 UTF-8 语言环境,则不会生成十六进制 0xFF 字节;这不是 UTF-8 中的有效字节(U+00FF 在 UTF-8 中被编码为两个字节 0xC3 0xBF)。

【讨论】:

  • 非常好的答案。使用int c 的另一个好处涉及后续使用is...() 函数,如isspace(),它期望值在unsigned char/EOF 的相同范围内。代码可以使用isspace(c)。使用char c,代码应使用isspace((unsigned char)c) 以避免UB。
【解决方案2】:

在 C char 中它可能崩溃的原因没有指定为有符号或无符号。它可以在您的机器上运行良好,但在其他机器上可能会失败。 还有getchar()函数返回int值,所以你应该使用int变量来获取这个返回值。

【讨论】:

  • 为什么char被签名或未签名会导致崩溃?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多