使用int或char数据类型并使用K& R进行练习 - “The C programming language”一书?

时间:2018-02-16 18:46:45

标签: c

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

这是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() != EOF1作为值。 0值意味着1 NOT 等于getchar()EOF作为价值会向我们显示0实际上相等getchar(),对吗?

[附加问题] 我在Stack Overflow上看到了另一个关于EOFgetchar()数据类型的用户的另一个问题,但是,我无法理解{{的答案3}}

  

你的程序运行不正常;它无法区分   在EOF和255之间。

这意味着什么?你能解释一下吗?另外,我无法理解这意味着什么:

  

0到7(#255)和EOF可以表示为1111 .... 32   时间.....(假设4字节int)?那里&gt;这里不会有冲突。

Oliver Charlesworth

更新

谢谢大家!对此:

  

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个字节,以确保不会丢失数据并存储cint这样的32位值为EOF,包括它也是负值的符号。 我理解正确吗? 再次感谢!

3 个答案:

答案 0 :(得分:5)

您遗失的重要信息是这句话,来自specification of fgetcgetchar被定义为等同于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,这是安全的;从cchar的转换最糟糕的是实现定义。

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

unsigned char

您将无法区分EOF与文件中可能存在的某些字节值。变量的符号性是无关紧要的,EOF的实际值也是如此;重要的是,charchar 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因此,如果我们在系统上声明cchar并且默认为signed char,那么它仍然可以正常工作,但如果我们输入等于ASCII的字符,它将会搞乱128以上?

如果char已签名,则128以上字符的位模式将被解释为负符号值。当输入字符255(扩展ASCII中的nbsp)时,唯一真正的混乱将会发生,因为它将在被-1表示的系统上被解释为EOF

  

1.2相反,如果我们将c声明为char,系统默认为unsigned char,则getchar()将始终不等于EOF无论如何,因为我们无法存储负值,对吗?

这是正确的,它永远不会等于EOFunsigned char内的任何位模式最终都会在0..255(包括0和255)的范围内,当提升为int时与EOF进行比较。因此,即使getchar()实际返回EOF,该比较也将是错误的。

  

我们输入一些字符作为输入c = getchar()抓取此输入并将其转换为ASCII数,然后检查以确保它不等于EOF

没有进行ASCII转换;字符以ASCII字符开头(假设系统使用ASCII)或者系统正在使用的任何编码样式的字符。

  
      
  1. 如果它不等于EOF,则会将输入字符显示为输出。

  2.   
  3. 它返回的状态是我们必须输入新字符才能继续循环。

  4.   

在3和4上都正确。

答案 2 :(得分:0)

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