为什么 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,通常是完全错误的,不应使用.
话虽如此,两个 你给出的例子实际上并没有这样做。
其中一个使用fseek
和ftell
来获取文件中的字节数,然后使用that来控制read/write 环形。这可能会有问题,因为文件的大小实际上可以在 之后发生变化 检索到大小,但这与试图将 int
强制转换为 char
是不同的问题。
另一个在读取字符后立即使用feof
来检查是否已到达文件末尾。
但是你是对的,最简单的方法就是正确使用 return 值,例如:
int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
doSomethingWith(charInt);
好吧,你当时看到的大部分代码都是错误的。有 3 种类型的 char
- signed
、unsigned
和纯字符。现在,如果默认情况下对普通字符进行签名,则具有十进制值 255
的字符将被视为等于 -1
(EOF)。这不是你想要的。 (是的,十进制值 255
不能用 signed char 表示,但它是实现定义的行为,在大多数情况下,它将位模式 0xFF
存储在 char
中)。
其次,如果 char
是 unsigned
那么它 EOF
将被认为是 0xFF
现在也是错误的,比较将失败。 (知道 EOF
是 -1
它将被转换为 CHAR_MAX
即 255
或 0xFF
)。
这就是为什么要考虑 int
,以便它可以正确地保存 EOF
的值,这就是您应该如何使用它。
我想将二进制文件源复制到文件目标。而已!该代码的灵感来自于 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,通常是完全错误的,不应使用.
话虽如此,两个 你给出的例子实际上并没有这样做。
其中一个使用fseek
和ftell
来获取文件中的字节数,然后使用that来控制read/write 环形。这可能会有问题,因为文件的大小实际上可以在 之后发生变化 检索到大小,但这与试图将 int
强制转换为 char
是不同的问题。
另一个在读取字符后立即使用feof
来检查是否已到达文件末尾。
但是你是对的,最简单的方法就是正确使用 return 值,例如:
int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
doSomethingWith(charInt);
好吧,你当时看到的大部分代码都是错误的。有 3 种类型的 char
- signed
、unsigned
和纯字符。现在,如果默认情况下对普通字符进行签名,则具有十进制值 255
的字符将被视为等于 -1
(EOF)。这不是你想要的。 (是的,十进制值 255
不能用 signed char 表示,但它是实现定义的行为,在大多数情况下,它将位模式 0xFF
存储在 char
中)。
其次,如果 char
是 unsigned
那么它 EOF
将被认为是 0xFF
现在也是错误的,比较将失败。 (知道 EOF
是 -1
它将被转换为 CHAR_MAX
即 255
或 0xFF
)。
这就是为什么要考虑 int
,以便它可以正确地保存 EOF
的值,这就是您应该如何使用它。