为什么不能使用char

为什么不能使用char,c,C,我是C的新手。书中有一个示例代码: #include <stdio.h> main() { int c; c = getchar(); while (c != EOF) { putchar(c); c = getchar(); } } 作者写了这样一句话: #include <stdio.h> main() { char c=getchar(); while (c != EOF) { putchar(c);

我是C的新手。书中有一个示例代码:

#include <stdio.h>

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

  while (c != EOF) {
    putchar(c);
    c = getchar();
  }
}
作者写了这样一句话:

#include <stdio.h>

main() {
  char c=getchar();

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

  if (c == EOF) {
    putchar('*');
  }
}
我们不能使用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,这让我很困惑。有人能解释一下吗?

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

另外,在相关注释中。另一方面,在C++中,字符文本具有类型字符。因此,您将看到通常作为int类型传递给C标准库函数和从C标准库函数返回的字符。

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

另外,在相关注释中。另一方面,在C++中,字符文本具有类型字符。因此,您将看到通常作为int类型传递给C标准库函数和从C标准库函数返回的字符。

char至少在您的系统上是有符号的。因此,它可以保存从-128到127的值

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

代码可以工作,因为保留了-1。但是,只要输入相当于255的字符,就会得到错误的-1。

字符至少在您的系统上是有符号的。因此,它可以保存从-128到127的值

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

代码可以工作,因为保留了-1。但是,一旦您输入了相当于255的字符,您也会得到错误的-1。

当您按CTRL-D时,getchar返回一个与char不匹配的值。所以char尽可能多地使用它。让我们假设EOF有一个公共数字:0xFFFFFFFF,换句话说,-1。当这个值被分配给char(假设它是有符号的)时,它将从中得到一个截断的值0xFF,也就是-1

因此,您的if变成:

char-1被提升为int,以便能够将其与int-1进行比较。因为在提升有符号值时,它们会得到符号扩展以保持原始有符号值,所以最终会比较-1和-1,这是真的

也就是说,这是唯一的幸运。如果您实际读取值为0xFF的字符,则会将其与EOF错误。更不用说EOF一开始可能不是-1。除此之外,除非您知道自己在做什么,否则不应该让程序在赋值给变量时截断值。

当您按CTRL-D时,getchar返回一个不适合char的值。所以char尽可能多地使用它。让我们假设EOF有一个公共数字:0xFFFFFFFF,换句话说,-1。当这个值被分配给char(假设它是有符号的)时,它将从中得到一个截断的值0xFF,也就是-1

因此,您的if变成:

char-1被提升为int,以便能够将其与int-1进行比较。因为在提升有符号值时,它们会得到符号扩展以保持原始有符号值,所以最终会比较-1和-1,这是真的

也就是说,这是唯一的幸运。如果您实际读取值为0xFF的字符,则会将其与EOF错误。更不用说EOF一开始可能不是-1。除此之外,除非您知道自己在做什么,否则不应该让程序在赋值给变量时截断值。

执行值转换后,getchar的结果将存储为achar。本例中的值可能是EOF-1

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

将整数类型的值转换为其他整数类型时 除了_Bool,如果值可以用新类型表示,则 没有变化

在您的while条件下的值比较过程中,通过转换进行值比较也会考虑到这一点:

6.5.9-p4相等运算符

如果两个操作数都具有算术类型,则执行通常的算术转换。如果和,则复杂类型的值相等 只有当它们的实部和虚部相等时 他们是平等的。来自不同类型的算术类型的任意两个值 当且仅当域的转换结果为 由常用算法确定的复杂结果类型 转化率是相等的

char和int都是整数类型。两者都可以在您的平台上保存整数值-1。因此,您的代码可以工作。

执行值转换后,getchar的结果将存储为achar。本例中的值可能是EOF-1

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

将整数类型的值转换为其他整数类型时 除了_Bool,如果值可以用新类型表示,则 没有变化

在您的while条件下的值比较过程中,通过转换进行值比较也会考虑到这一点:

6.5.9-p4相等运算符

如果两个操作数都具有算术类型,则执行通常的算术转换。如果和,则复杂类型的值相等 只有当它们的实部和虚部相等时 他们是平等的。来自不同类型的算术类型的任意两个值 当且仅当域的转换结果为 由常用算法确定的复杂结果类型 转化率是相等的


char和int都是整数类型。两者都可以在您的平台上保存整数值-1。因此,您的代码可以正常工作。

类型char是一个无符号的8位值。实际上,我认为对于标准ASCII表,它可以是7位,但我从未见过它这样实现

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


此外,可能会编写一些代码来查找返回值类型char是一个无符号8位值,实际上我认为对于标准ASCII表,它可以是7位,但我从未见过它这样实现

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


此外,可能会编写一些代码以查找返回值Try indenting您的代码correctly@Zhenxiao郝读了这篇文章的答案:getchar的签名是int-getcharvoid。将函数的返回值存储在变量中或与返回值相同的类型中是一种很好的做法。如果函数返回int,则将其结果存储在int中。不可能是字符的具体原因由提供。请尝试缩进代码correctly@Zhenxiao郝读了这篇文章的答案:getchar的签名是int-getcharvoid。将函数的返回值存储在变量中或与返回值相同的类型中是一种很好的做法。如果函数返回int,则将其结果存储在int中。不可能是字符的具体原因由提供。