首页 文章

使用int或char数据类型并使用K&R进行练习 - “C编程语言”一书?

提问于
浏览
1

首先,请原谅我提出这个问题,因为已有数十种类似的变体 . 但是,我不完全确定如果我能正确理解它 . 所以,请让我解释一下我能理解的内容,如果我错了,请纠正我 .

这是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)所以,如果我们在系统上声明 cchar 并且它默认为 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 将输出 10 作为值 . 1 值意味着 getchar() NOT 等于 EOF . 0 作为值会告诉我们 getchar() 实际上是 equalEOF ,对吗?

[附加问题]我在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)?那里>将不会有冲突 .

如果我在下面的所有答案和解释之后正确理解它 . 这意味着具有值 -1EOF 将表示为 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 回答

  • 0

    您缺少的关键信息是这句话,来自specification of fgetcgetchar 被定义为等同于 fgetc(stdin) ):

    如果未设置stream指向的输入流的文件结束指示符并且存在下一个字符,则fgetc函数[返回]将该字符作为unsigned char转换为int . [否则,它返回EOF . ]

    强调我的 . 这意味着,在 unsigned char 可以表示0到255(包括0和255)的典型实现中, getchar 将始终返回0到255(包括0和255)范围内的值,或EOF,即使 char 已签名 .

    同时,EOF不保证为-1(虽然它几乎总是如此),但它保证是负的,并且适合 int .

    所以,当你这样做的时候

    int c = getchar();
    

    你可以确定没有任何可能的返回值相互冲突: c 将是 EOF ,这是负数,或者它将是 unsigned char (0到255)可表示的值之一,它们都是非负的 . 如果在检查到它不是EOF之后将 c 转换回 char ,则这是安全的;从 unsigned charchar 的转换是最差的实现定义 .

    另一方面,当你做任何这些

    char c = getchar();          // this is wrong
    unsigned char d = getchar(); // also wrong
    signed char e = getchar();   // also wrong
    

    你失去了区分EOF和文件中可能存在的字节值的能力 . 变量的符号性是无关紧要的,EOF的实际值也是如此;重要的是 charunsigned charsigned char 只能表示2CHAR_BIT个不同的值,所有这些值都可以在文件中,而EOF则是另一个 . 这是pigeonhole principle .

    您应该知道K&R已经很老了,不再被认为是学习C的最佳书籍 . (我不知道目前最好的书是什么 . )

  • 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都正确 .

  • 5

    在每个普通系统上,char是8位 . 所以它取值0-255 . 像fgetc()这样的函数需要能够返回0-255,加上EOF的-1 . 所以他们返回一个int而不是一个char,我们倾向于传递单个字符作为int而不是char来顺利处理EOF .

相关问题