首先,请原谅我提出这个问题,因为已有数十种类似的变体 . 但是,我不完全确定如果我能正确理解它 . 所以,请让我解释一下我能理解的内容,如果我错了,请纠正我 .
这是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及以上的字符,它会搞乱吗? What will happen?getchar()
将返回所选数据类型的最大可能ASCII值值127? -
1.2)相反,如果我们将
c
声明为char
,并且系统默认为unsigned char
,那么getchar()
将始终 NOT 等于EOF
,无论如何因为我们无法存储负值, right?
因为上面的所有变体都正确地将 c
声明为 int
以避免可能的冲突?
2)我们输入一些字符作为输入 c = getchar()
抓取此输入并将其转换为ASCII数,然后检查以确保它不等于 EOF
.
3)如果 NOT 等于 EOF
,则显示输入字符作为输出 .
4)它返回到我们必须输入新字符以继续循环的状态 .
以上都是正确的吗?
[附加问题]此外,语句 getchar() != EOF
将输出 1
或 0
作为值 . 1
值意味着 getchar()
NOT 等于 EOF
. 0
作为值会告诉我们 getchar()
实际上是 equal 到 EOF
,对吗?
[附加问题]我在Stack Overflow上看到另一个用户关于 getchar()
和 char
数据类型的另一个问题,但是,我无法理解Oliver Charlesworth的答案 .
你的程序不能正常工作;它无法区分EOF和255 .
那意味着什么?你能解释一下吗?另外,我也无法理解这意味着什么:
0到7(#255)和EOF可以表示为1111 .... 32次.....(假设4字节为int)?那里>将不会有冲突 .
Link to the Oliver Charlesworth's answer.
UPDATE
谢谢你们!关于这个:
0到7(#255)和EOF可以表示为1111 .... 32次.....(假设4字节为int)?那里>将不会有冲突 .
如果我在下面的所有答案和解释之后正确理解它 . 这意味着具有值 -1
的 EOF
将表示为 1111 1111
,例如,如果数据类型为 char
,那么它将认为's #255 because it'仅为8位且它将完全存储在内存中,因为它是0xFF(#255)而没有其他指示(简而言之:数据丢失现在而不是值 -1
它意味着完全不同的东西), is that correct? 因此,为了避免这种混淆,当我们将 c
声明为 int
时,我们会分配4个字节,以确保不会丢失任何数据它会将 EOF
值 -1
存储在32位中,如 32 times...1111 1111
,包括它也是负值的符号 . Do I understand it correctly? 再次感谢!
3 回答
您缺少的关键信息是这句话,来自specification of fgetc(
getchar
被定义为等同于fgetc(stdin)
):强调我的 . 这意味着,在
unsigned char
可以表示0到255(包括0和255)的典型实现中,getchar
将始终返回0到255(包括0和255)范围内的值,或EOF,即使char
已签名 .同时,EOF不保证为-1(虽然它几乎总是如此),但它保证是负的,并且适合
int
.所以,当你这样做的时候
你可以确定没有任何可能的返回值相互冲突:
c
将是EOF
,这是负数,或者它将是unsigned char
(0到255)可表示的值之一,它们都是非负的 . 如果在检查到它不是EOF之后将c
转换回char
,则这是安全的;从unsigned char
到char
的转换是最差的实现定义 .另一方面,当你做任何这些
你失去了区分EOF和文件中可能存在的字节值的能力 . 变量的符号性是无关紧要的,EOF的实际值也是如此;重要的是
char
,unsigned char
和signed char
只能表示2CHAR_BIT个不同的值,所有这些值都可以在文件中,而EOF则是另一个 . 这是pigeonhole principle .您应该知道K&R已经很老了,不再被认为是学习C的最佳书籍 . (我不知道目前最好的书是什么 . )
如果
char
已签名,则128以上字符的位模式将被解释为负符号值 . 当输入字符255
(扩展ASCII中的nbsp
)时,唯一真正的混乱将会发生,因为它将在-1表示的系统上被解释为EOF
.这是正确的,它永远不会等于
EOF
.unsigned char
中的任何位模式都会在0..255(包括0和255)的范围内结束,当提升为int
时,与EOF
进行比较 . 因此,即使getchar()
实际返回EOF
,比较也将为假 .没有进行ASCII转换;字符以ASCII字符开头(假设系统使用ASCII)或系统正在使用的任何编码样式的字符 .
在3和4都正确 .
在每个普通系统上,char是8位 . 所以它取值0-255 . 像fgetc()这样的函数需要能够返回0-255,加上EOF的-1 . 所以他们返回一个int而不是一个char,我们倾向于传递单个字符作为int而不是char来顺利处理EOF .