我是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
,这让我感到困惑。有人可以解释一下吗?
答案 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
尽可能多地接受它。我们假设EOF
:0xFFFFFFFF
的公共号,换句话说,-1。将此值分配给char
时(假设它已签名),它将从中获取截断值0xFF
,该值也为-1。
所以你的if
变为:
if ((char)-1 == (int)-1)
(char)-1
被提升为int
,以便能够将其与(int)-1
进行比较。由于在提升已签名的值时,会对符号进行扩展(以保留原始的有符号值),最后您需要比较-1
和-1
这是真的。
那就是说,这只是幸运的。如果您确实阅读了值为0xFF
的字符,则会将其误认为EOF
。更不用说EOF
首先可能不是-1。除此之外,你不应该让你的程序在分配变量时截断一个值(除非你知道你在做什么)。
答案 2 :(得分:1)
char
已签名。因此,它可以保存从-128
到127
的值。
EOF
是-1
,因此是其中之一。
您的代码有效,因为-1
会被保留。但只要您输入相当于255
的字符,您就会错误地-1
。
答案 3 :(得分:1)
执行转换按值后,getchar()
的结果将存储为char
。在这种情况下,值可能是EOF(-1)。
6.3.1.3-p1有符号和无符号整数
当整数类型的值转换为另一个整数类型时 除了_Bool之外,如果值可以用新类型表示,那么 没有改变。
在您通过转换进行价值比较时,您可以在余额条件下进行价值比较时考虑到这一点:
6.5.9-p4平等运营商
如果两个操作数都具有算术类型,则执行通常的算术转换。如果和,复杂类型的值相等 只有当他们的真实部分都是相同的,以及他们想象的部分 是平等的。来自不同类型的任何两个算术类型的值 当且仅当他们转换的结果时,域名是相等的 (复数)结果类型由通常的算术确定 转换是平等的。
char
和int
都是整数类型。两者都可以在您的平台上保存整数值(-1)。因此,您的代码“有效”。
答案 4 :(得分:1)
char类型是一个无符号的8位值(实际上我认为标准ASCII表可以是7位,但我从来没有看到它像那样实现)。
EOF是实现定义的,但通常为-1。这是一个带符号的数字(32位机器中为0xFFFFFFFF)。大多数编译器可能会将其截断为0xFF以与char进行比较,但这也是一个有效(但很少使用)的字符,因此您无法确定是否具有十六进制值255或EOF(-1)。
此外,可以编写一些代码以寻找<0的返回值以停止读取。显然,char永远不会小于零。