我正在研究C中的输入和输出方法,并且我看到了一段代码,其中包含一些我无法理解的元素。这段代码的目的是展示'echoing'和'buffered'输入/输出是如何工作的,并且在代码中,他们有一个'int'类型,据我所知,为字符声明:
#include <stdio.h>
int main(void){
int ch; //This is what I do not get: why is this type 'int'?
while((ch = getchar()) != '\n'){
putchar(ch);
}
return 0;
}
我并没有坚持使用类型转换,这种'int'/'char'的差异正在破坏我对数据类型和兼容性的所有概念。
答案 0 :(得分:4)
getchar()
会返回int
类型,因为它的设计能够返回char
无法表示的值,以表示EOF
。 (C.11§7.21.1¶3和§7.21.7.6¶3)
您的循环代码应考虑getchar()
可能会返回EOF
:
while((ch = getchar()) != EOF){
if (ch != '\n') putchar(ch);
}
答案 1 :(得分:3)
getc
,fgetc
和getchar
函数返回int,因为它们能够处理二进制数据,并提供错误或结束的带内信号。数据条件。
除了某些具有异常字节大小的嵌入式平台外,类型int
能够将0
到UCHAR_MAX
的所有字节值表示为正值。此外,它可以表示负值,例如常量EOF
的值。
类型unsigned char
只能表示值0
到UCHAR_MAX
,因此函数无法使用返回值作为指示无法使用的方法读取另一个数据字节。值EOF
很方便,因为它可以被视为输入符号;例如,它可以包含在处理各种字符的switch
语句中。
还有一点,因为在C的设计中,short
和char
类型(有符号或无符号)的值在评估时会进行促销在表达式中。
在经典C中,在引入原型之前,当您将char
传递给函数时,它实际上是传递的int
值。具体地:
int func(c)
char c;
{
/* ... */
}
这种旧样式定义不会引入有关参数类型的信息。
当我们将其称为func(c)
,其中c
的类型为char
时,表达式c
将受到常规促销的约束,并成为int
类型的值。这正是上述函数定义所期望的类型。 char
类型的参数实际上作为类型int
的值传递。如果我们为上述函数编写ISO C原型声明,那么必须猜测:
int func(int); /* not int func(char) */
另一个遗产是像'A'
这样的字符常量实际上有int
而不是char
。值得注意的是,C ++中的这种变化,因为C ++有重载函数。鉴于过载:
void f(int);
void f(char);
我们希望f(3)
调用前者,f('A')
调用后者。
所以重点是C的设计者基本上认为char
是面向紧凑的存储位置,以及最小的可寻址存储单元。但就处理器中的数据操作而言,他们认为值是字大小的int
值:字符处理本质上是基于int
的数据操作。
这是C的低级方面之一。在字节可寻址机器上的机器语言中,我们通常将字节视为存储单元,当我们加载到寄存器中以使用它们时,它们占用一个完整的寄存器,因此成为32位值(或者你有什么)。这反映在C语言中的推广概念中。
答案 2 :(得分:1)
getchar()
的返回类型为int
。它返回刚才读取的字符的ASCII码。这是(我知道有人会纠正我)与char
表示相同,所以你可以自由地比较它们等等。
为什么会这样? getchar()
函数很古老 - 从K&amp; R C的最早期开始。putchar()
同样需要int
个参数,当你认为它可能需要char
时}。
希望有所帮助!