3

K&R 提供了这个getchar()例子:

int getchar(void)
{
    char c;

    return (read(0, &c, 1) == 1) ? (unsigned char) c : EOF;
}

c被强制转换到unsigned char这里以避免符号扩展问题,但在fputs()示例中......

int fputs(char *s, FILE *iop)
{
    int c;

    while (c = *s++)
        putc(c, iop);
    return ferror(iop) ? EOF : 0;
}

*s被分配给 aint而没有首先转换为 a unsigned char。为什么这次不需要演员阵容?

4

3 回答 3

3

这与“标志扩展问题”无关。这个实现getchar确保所有成功读取的字符都作为非负值 int返回。这种行为是 的规范所要求的getchar,它的字面意思是读取的字符作为unsigned char转换为 的值返回int,即使char在给定平台上签名也是如此。你看到的基本上是getchar规范的直接实现。

同时fputs不返回任何特定的字符值。fputs不返回c给用户。那c是一个纯粹的内部变量。char它应该保留给定平台上 type的原始值,因为 的值c随后被传递给putc. putc不期望将字符值转换为非负范围,它期望原始字符值,如果char有符号则很容易为负。

顺便说一句,你为什么看fputs,而不是fputc?如果你看一下fputc,它就像getchar返回一个字符值,你可能会看到它getchar在这方面的实现方式类似。

于 2013-09-19T03:16:29.687 回答
2

我第一次完全误解了这个问题。这里的问题是getchar()需要返回char0-255 范围内的 a 或EOF. 在大多数平台上EOF = -1。为了返回负值和字符,必须使用 int。

情况并非如此fputs。在此示例中,在 while 循环中将 achar分配给 an int。“低级”类型被提升为“高级”类型。从第 44 页 KR,C 编程语言:

如果任一操作数是 a long double,则将另一个操作数转换为 a long double
否则,如果任一操作数是 a double,则将另一个操作数转换为 a double
否则,如果任一操作数是 a float,则将另一个操作数转换为 a float
否则,将charand转换shortint
然后,如果任一操作数是 a long,则将另一个转换为long

于 2013-09-19T03:15:01.830 回答
1

根据手册页,

fputc()函数将字符c(转换为unsigned char)写入 指向的输出流stream

强制转换是在函数内部专门为您执行的。

除此之外,分配 fromchar到负数int并返回 tochar可以保证产生正确的结果,并且charto 负数intto保证与直接转换 from tounsigned char具有相同的结果。其他情况可能会产生有符号整数溢出,从而产生未定义的行为(即,可能崩溃)。但是大多数平台通过安静的二进制截断来处理它,这样许多程序员根本不会担心它。charunsigned char

于 2013-09-19T03:23:38.500 回答