为什么将fgetc()返回到char iso int?

geo*_*hei 1 c variables fgetc

我想将二进制文件源复制到文件目标.而已!该代码的灵感来自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;

}
Run Code Online (Sandbox Code Playgroud)

结果文件大小不同.

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
Run Code Online (Sandbox Code Playgroud)

好的,那有什么问题呢?

我知道char是未签名的,并且在80以上时签名.请看这里.

这在我使用时得到证实,printf("%x\n", ch);它有时会返回大约50%的时间FFFFFFE1.

我的问题的解决方案是使用intiso char.

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

找到的示例int:示例a,...

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

为什么几乎所有代码示例都发现将fgetc()返回到chariso a int,哪个更正确?

我错过了什么?

pax*_*blo 5

ISO C强制要求fgetc()返回,int因为除了文件结束指示符之外,它必须能够返回每个可能的字符.

这样会将返回值转换成代码char,使用它来检测EOF,一般是完全错误的,不应该被使用.


话虽如此,你提供的两个例子实际上并没有这样做.

其中一个使用fseekftell获取文件中的字节数,然后使用来控制读/写循环.这可能会有问题,因为文件在检索到大小实际上可以改变大小,但是尝试强制int进入文件时这是一个不同的问题char.

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


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

int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
    doSomethingWith(charInt);
Run Code Online (Sandbox Code Playgroud)


use*_*738 5

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

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

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

  • 很好的答案,因为它涵盖了我没有想到的额外方面,即签名问题。 (2认同)