我正在研究C中的输入和输出方法,并且我看到了一段代码,其中包含一个我无法理解的元素。这段代码的目的是展示"回显"和"缓冲"输入/输出的工作原理,并且在代码中,它们有一个类型"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"差异破坏了我对数据类型和兼容性的所有概念。
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);
}
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
的数据操作。
在字节可寻址机器上的机器语言中,我们通常认为字节是存储单元,当我们加载到寄存器中以使用它们时,它们占据了一个完整的寄存器,因此成为32位值(或者你有什么)。这反映在 C 语言中的晋升概念中。
getchar()
的返回类型是 int
。它返回刚刚读取的字符的 ASCII 代码。这是(我知道有人会纠正我)与char
表示相同,因此您可以自由比较它们等等。
为什么会这样?getchar()
函数是古老的——从K&R C的早期开始。 putchar()
同样需要一个int
论点,当你认为可能需要一个char
时。
希望对您有所帮助!