首先,请原谅我提出这个问题,因为已有数十种类似的变体。但是,我不完全确定如果我能正确理解它。所以,请让我解释一下我能理解的内容,如果我错了,请纠正我。
这是K& R书中的一个例子:
#include <stdio.h>
main()
{
1) int c;
2) 4) while ((c = getchar()) != EOF)
3) putchar(c);
}
所以,我理解上面这样的程序:
1)我们将c
声明为int
而不是char
,因为使用char
数据类型并不总能正常运行最终会弄乱它。 Char
数据类型的变化取决于系统,默认情况下可能是signed
[-127,+ 127]或unsigned
[0,255]。此外,EOF
默认情况下并不总是-1
,因为它还取决于系统和编译器。
1.1)因此,如果我们在系统上将c
声明为char
并且默认为signed char
,那么它仍然可以正常工作如果我们输入一个等于ASCII 128及以上的字符会搞砸? 将会发生什么? getchar()
将为所选数据类型返回最大可能ASCII值的值,127?
1.2)相反,如果我们将c
声明为char
,系统默认为unsigned char
,则{{1} } <= 1>}总是 NOT 等于getchar()
因为我们无法存储负值,对吗?
因为上面的所有变体都正确地将EOF
声明为c
以避免可能的冲突?
2)我们输入一些字符作为输入int
抓取此输入并将其转换为ASCII数,然后检查以确保它不等于c = getchar()
。
3)如果 NOT 等于EOF
,则会将输入字符显示为输出。
4)它返回到我们必须输入新字符以继续循环的状态。
以上都是正确的吗?
[其他问题] 此外,语句EOF
将输出getchar() != EOF
或1
作为值。 0
值意味着1
NOT 等于getchar()
。 EOF
作为价值会向我们显示0
实际上相等到getchar()
,对吗?
[附加问题] 我在Stack Overflow上看到了另一个关于EOF
和getchar()
数据类型的用户的另一个问题,但是,我无法理解{{的答案3}}
你的程序运行不正常;它无法区分 在EOF和255之间。
这意味着什么?你能解释一下吗?另外,我无法理解这意味着什么:
0到7(#255)和EOF可以表示为1111 .... 32 时间.....(假设4字节int)?那里&gt;这里不会有冲突。
更新
谢谢大家!对此:
char
如果在下面的所有答案和解释之后我理解正确的话。这意味着值为0 through 7 (# 255) and EOF can be represented as 1111....32
times..... (assuming a 4 byte int)? There > will be no conflict
here.
的{{1}}将表示为EOF
,如果数据类型为-1
,那么它会认为它是#255,因为它只有8位且它将被存储在内存中,与0xFF(#255)完全没有其他指示(简言之:数据丢失,现在而不是值1111 1111
,这意味着完全不同的东西),是正确吗?因此,为了避免这种混淆,我们在将char
声明为-1
时分配4个字节,以确保不会丢失数据并存储c
像int
这样的32位值为EOF
,包括它也是负值的符号。 我理解正确吗?
再次感谢!
答案 0 :(得分:5)
您遗失的重要信息是这句话,来自specification of fgetc
(getchar
被定义为等同于fgetc(stdin)
):
如果未设置stream指向的输入流的文件结束指示符并且存在下一个字符,则fgetc函数[返回]将该字符转换为
unsigned char
转换为int
的。 [否则,它会返回EOF
。]
强调我的。这意味着,在unsigned char
可以表示值0到255(包括0和255)的典型实现中,getchar
将始终返回0到255(包括0和255)范围内的值,或EOF,,即使{ {1}}已签名。
同时,EOF不保证为-1(尽管几乎总是如此),但 保证为负,并且适合char
。
所以,当你这样做时
int
您可以确定任何可能的返回值都不会相互冲突:int c = getchar();
将为c
,这是负数,或者它将是{{1}可表示的值之一(0到255),都是非负的。如果您在之后将EOF
转换回unsigned char
,那么您已经检查过它不是EOF,这是安全的;从c
到char
的转换最糟糕的是实现定义。
另一方面,当你做任何这些
时unsigned char
您将无法区分EOF与文件中可能存在的某些字节值。变量的符号性是无关紧要的,EOF的实际值也是如此;重要的是,char
,char c = getchar(); // this is wrong
unsigned char d = getchar(); // also wrong
signed char e = getchar(); // also wrong
和char
只能代表2个 CHAR_BIT 不同的值,所有这些值都可以在文件中,并且EOF是多一个。这是pigeonhole principle。
你应该知道K&amp; R已经很老了,不再被认为是学习C的最佳书。 (我不知道目前最好的书是什么。)
答案 1 :(得分:3)
1.1因此,如果我们在系统上声明
c
为char
并且默认为signed char
,那么它仍然可以正常工作,但如果我们输入等于ASCII的字符,它将会搞乱128以上?
如果char
已签名,则128以上字符的位模式将被解释为负符号值。当输入字符255
(扩展ASCII中的nbsp
)时,唯一真正的混乱将会发生,因为它将在被-1表示的系统上被解释为EOF
1.2相反,如果我们将
c
声明为char
,系统默认为unsigned char
,则getchar()
将始终不等于EOF
无论如何,因为我们无法存储负值,对吗?
这是正确的,它永远不会等于EOF
。 unsigned char
内的任何位模式最终都会在0..255(包括0和255)的范围内,当提升为int
时与EOF
进行比较。因此,即使getchar()
实际返回EOF
,该比较也将是错误的。
我们输入一些字符作为输入
c = getchar()
抓取此输入并将其转换为ASCII数,然后检查以确保它不等于EOF
。
没有进行ASCII转换;字符以ASCII字符开头(假设系统使用ASCII)或者系统正在使用的任何编码样式的字符。
如果它不等于
EOF
,则会将输入字符显示为输出。- 醇>
它返回的状态是我们必须输入新字符才能继续循环。
在3和4上都正确。
答案 2 :(得分:0)
在每个普通系统上,char是8位。所以它取值0-255。像fgetc()这样的函数需要能够返回0-255,加上EOF的-1。所以他们返回一个int而不是一个char,我们倾向于传递单个字符作为int而不是char来顺利处理EOF。