为什么不能使用char

时间:2014-01-22 17:32:34

标签: c

我是C的新手。从书中可以看到一个示例代码:

#include <stdio.h>

main() {
  int c;
  c = getchar();

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

作者写了这样一句话:

  

我们不能使用char,因为除了任何可能的char之外,c必须足够大以容纳EOF。因此我们使用int。

试图理解,我修改了这样的代码:

#include <stdio.h>

main() {
  char c=getchar();

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

  if (c == EOF) {
    putchar('*');
  }
}

当我按 Ctrl + D 时,会打印*,这意味着c拥有EOF,这让我感到困惑。有人可以解释一下吗?

5 个答案:

答案 0 :(得分:4)

因为EOF是一个特殊的标记值(实现已定义,但通常为-1作为int类型),如果存储在{{1}中,则无法将其与值255区分开来变量。您需要一个大于8位的类型,以表示char返回的所有可能的字节值,以及特殊的标记值getchar()EOF有257种不同的可能返回值。

另外,在相关说明中,character literals in C like 'a' have the type int。另一方面,在C ++中,字符文字的类型为getchar()。因此,您将看到通常传递给C标准库函数并从char类型返回的字符。

答案 1 :(得分:3)

当您按CTRL-D时,getchar()会返回一个不适合char的值。所以char尽可能多地接受它。我们假设EOF0xFFFFFFFF的公共号,换句话说,-1。将此值分配给char时(假设它已签名),它将从中获取截断值0xFF,该值也为-1。

所以你的if变为:

if ((char)-1 == (int)-1)

(char)-1被提升为int,以便能够将其与(int)-1进行比较。由于在提升已签名的值时,会对符号进行扩展(以保留原始的有符号值),最后您需要比较-1-1这是真的。

那就是说,这只是幸运的。如果您确实阅读了值为0xFF的字符,则会将其误认为EOF。更不用说EOF首先可能不是-1。除此之外,你不应该让你的程序在分配变量时截断一个值(除非你知道你在做什么)。

答案 2 :(得分:1)

至少在您的系统上,

char已签名。因此,它可以保存从-128127的值。

EOF-1,因此是其中之一。

您的代码有效,因为-1会被保留。但只要您输入相当于255的字符,您就会错误地-1

答案 3 :(得分:1)

执行转换按值后,getchar()的结果将存储为char。在这种情况下,值可能是EOF(-1)。

  

6.3.1.3-p1有符号和无符号整数

     

当整数类型的值转换为另一个整数类型时   除了_Bool之外,如果值可以用新类型表示,那么   没有改变。

在您通过转换进行价值比较时,您可以在余额条件下进行价值比较时考虑到这一点:

  

6.5.9-p4平等运营商

     

如果两个操作数都具有算术类型,则执行通常的算术转换。如果和,复杂类型的值相等   只有当他们的真实部分都是相同的,以及他们想象的部分   是平等的。来自不同类型的任何两个算术类型的值   当且仅当他们转换的结果时,域名是相等的   (复数)结果类型由通常的算术确定   转换是平等的。

charint都是整数类型。两者都可以在您的平台上保存整数值(-1)。因此,您的代码“有效”。

答案 4 :(得分:1)

char类型是一个无符号的8位值(实际上我认为标准ASCII表可以是7位,但我从来没有看到它像那样实现)。

EOF是实现定义的,但通常为-1。这是一个带符号的数字(32位机器中为0xFFFFFFFF)。大多数编译器可能会将其截断为0xFF以与char进行比较,但这也是一个有效(但很少使用)的字符,因此您无法确定是否具有十六进制值255或EOF(-1)。

此外,可以编写一些代码以寻找<0的返回值以停止读取。显然,char永远不会小于零。