gpt4 book ai didi

c - getchar/fgetc和putchar/fputc中的int和char之间的区别?

转载 作者:行者123 更新时间:2023-11-30 16:23:40 25 4
gpt4 key购买 nike

我试图自己学习C,并且对getcharputchar感到困惑:

1个

#include <stdio.h>

int main(void)
{
char c;
printf("Enter characters : ");
while((c = getchar()) != EOF){
putchar(c);
}
return 0;
}


2

#include <stdio.h>

int main(void)
{
int c;
printf("Enter characters : ");
while((c = getchar()) != EOF){
putchar(c);
}
return 0;
}


C库函数 int putchar(int c)将由参数char指定的字符(无符号char)写入stdout。

C库函数 int getchar(void)从stdin获取一个字符(无符号字符)。这等效于以stdin作为参数的getc。

这是否意味着 putchar()接受 intchar或两者都接受?对于 getchar(),我们应该使用 int还是 char

最佳答案

TL; DR:


char c; c = getchar();是错误的,损坏的和有故障的。
int c; c = getchar();是正确的。


这甚至也适用于getcfgetc,因为甚至经常读到文件末尾。



始终始终将getcharfgetcgetc ...)(和putchar)的返回值最初存储在类型为int的变量中。

putchar的参数可以是intcharsigned charunsigned char中的任何一个;它的类型无关紧要,并且所有字符都一样工作,即使一个字符可能会导致对包含\200(128)以上的字符传递正整数和负整数。



必须使用int来存储getcharputchar的返回值的原因是,当达到文件结束条件(或发生I / O错误)时,它们都返回宏EOF的值,它是负整数常量(usually -1)

对于getchar,如果返回值不是EOF,则它是读取的unsigned char零扩展到int的值。也就是说,假设使用8位字符,则返回的值可以是0 ... 255或宏EOF的值;再次假设为8位字符,则无法将这257个不同的值压缩为256个,以便可以唯一地标识每个值。



现在,如果将其存储在char中,效果将取决于the character type is signed or unsigned by default!这在编译器之间,编译器之间,架构在体系结构之间有所不同。如果对char进行了签名并假定将EOF定义为-1,则输入中的EOF和字符'\377'都将等于EOF;它们将被符号扩展到(int)-1

另一方面,如果char是无符号的(这在ARM处理器上默认为包括[aa>;对于Raspberry PI systems似乎是正确的)),则在c中没有可以存储的值将比较等于-1;包括EOF;您的代码将输出单个EOF字符,而不是在\377上中断。

此处的危险在于,即使使用签名的char,该代码仍会严重损坏,但似乎仍可以正常工作-合法输入值之一被解释为EOF。此外,C89,C99,C11不要求EOF的值。它只说EOF是一个负整数常量;因此,在特定实现上也可以用-1代替-224,这将导致空格的行为类似于EOF

gcc具有开关-funsigned-char,该开关可用于在默认为已签名的那些平台上使char为未签名:

% cat test.c
#include <stdio.h>

int main(void)
{
char c;
printf("Enter characters : ");
while((c= getchar()) != EOF){
putchar(c);
}
return 0;
}


现在,我们用签名的 char运行它:

% gcc test.c && ./a.out
Enter characters : sfdasadfdsaf
sfdasadfdsaf
^D
%


似乎工作正常。但是使用未签名的 char

% gcc test.c -funsigned-char && ./a.out                   
Enter characters : Hello world
Hello world
���������������������������^C
%


也就是说,我尝试多次按 Ctrl-D,但是为每个 打印了 EOF而不是打破循环。

现在,再次,对于带符号的 char案例,它无法在Linux上区分 char 255和 EOF,从而破坏了二进制数据,例如:

% gcc test.c && echo -e 'Hello world\0377And some more' | ./a.out 
Enter characters : Hello world
%


直到 \0377转义的只有第一部分被写入stdout。



请注意,字符常量与包含无符号字符值的 int之间的比较可能无法按预期进行(例如,ISO 8859-1中的字符常量 'ä'表示带符号的值 -28。因此,假设您编写的代码会一直读取输入,直到ISO 8859-1代码页中的 'ä'为止,

int c;
while((c = getchar()) != EOF){
if (c == (unsigned char)'ä') {
/* ... */
}
}




由于整数提升,所有 char值都适合 int,并在函数调用时自动提升,因此您可以将 intcharsigned charunsigned char中的任何一个赋予 putchar作为参数(不存储其返回值),它将按预期工作。

传递给整数的实际值可能为正,甚至为负;例如,在带有 \377的8位字符系统中,字符常量 char为负。但是 putchar(或 fputc实际上)会将值转换为无符号字符。 AIX too


  2 fputc函数将 c指定的字符(转换为无符号字符)写入流指向的输出流[...]


(强调我的)

fputc可以保证像 c那样转换给定的 (unsigned char)c

关于c - getchar/fgetc和putchar/fputc中的int和char之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53924969/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com