为什么 fgetc() return int 而不是 char?

Why does fgetc() return int instead of char?

我想将二进制文件源复制到文件目标。而已!该代码的灵感来自于 Internet 上找到的许多示例。

#include <stdio.h>

int main(int argc, char **argv) {

    FILE *fp1, *fp2;
    char ch;

    fp1 = fopen("source.pdf", "r");
    fp2 = fopen("target.pdf", "w");

    while((ch = fgetc(fp1)) != EOF)
        fputc(ch, fp2);

    fclose(fp1);
    fclose(fp2);

    return 0;

}

结果文件大小不同。

root@vm:/home/coder/test# ls -l
-rwxr-x--- 1 root root 14593 Feb 28 10:24 source.pdf
-rw-r--r-- 1 root root   159 Mar  1 20:19 target.pdf

好的,有什么问题吗?

我知道 char 是无符号的,超过 80 时会被签名。参见

这在我使用 printf("%x\n", ch); 时得到证实,其中 returns 大约有 50% 的时间类似于 FFFFFFE1.

我的问题的解决方案是使用 int i.s.o。 char.

使用 char 找到的示例:example 1, example 2 example 3, example 4, ...

找到 int 的示例:example a、...

我不使用花哨的编译器选项。

为什么发现几乎所有代码示例都将 fgetc() 返回到 char i.s.o。一个 int,哪个更正确?

我错过了什么?

ISO C 要求 fgetc() return 是 int 因为它必须能够 return 除了 [=] 之外的每个可能的字符 38=] 一个 end-of-file 指标。

因此,将 return 值放入 char 中的代码使用它来检测 EOF,通常是完全错误的,不应使用.


话虽如此,两个 你给出的例子实际上并没有这样做。

其中一个使用fseekftell来获取文件中的字节数,然后使用that来控制read/write 环形。这可能会有问题,因为文件的大小实际上可以在 之后发生变化 检索到大小,但这与试图将 int 强制转换为 char 是不同的问题。

另一个在读取字符后立即使用feof来检查是否已到达文件末尾。


但是你是对的,最简单的方法就是正确使用 return 值,例如:

int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
    doSomethingWith(charInt);

好吧,你当时看到的大部分代码都是错误的。有 3 种类型的 char - signedunsigned 和纯字符。现在,如果默认情况下对普通字符进行签名,则具有十进制值 255 的字符将被视为等于 -1 (EOF)。这不是你想要的。 (是的,十进制值 255 不能用 signed char 表示,但它是实现定义的行为,在大多数情况下,它将位模式 0xFF 存储在 char 中)。

其次,如果 charunsigned 那么它 EOF 将被认为是 0xFF 现在也是错误的,比较将失败。 (知道 EOF-1 它将被转换为 CHAR_MAX2550xFF)。

这就是为什么要考虑 int,以便它可以正确地保存 EOF 的值,这就是您应该如何使用它。