0

以下程序旨在制作一个.exe应用程序文件的副本。但只有一件小事决定了它是否确实为我提供了预期文件RealPlayer.exe的正确副本或给我一个损坏的文件。

我所做的是以二进制模式从源文件中读取并以相同的模式写入新副本。为此,我使用了一个变量ch。但是如果ch是类型char,我会得到一个损坏的文件,它的大小只有几个字节,而原始文件为26MB 但如果我将类型更改为两部分:chint

1)为什么在类型工作时使用类型charch搞砸事情int?类型有什么问题char?毕竟,它不应该从原始文件中逐字节读取(就像char一个字节本身一样)并将其逐字节写入新的副本文件?毕竟不是int类型所做的,即从原始文件中读取 4 个字节,然后将其写入副本文件?为什么两者之间有区别?

2)char如果我们使用type for ,为什么文件与原始文件相比如此小ch?让我们暂时忘记复制的文件已损坏,并关注大小。为什么大小这么小如果我们逐个字符(或逐个字节)复制字符,但是当我们复制“整数乘整数”(或 4 字节乘 4 字节)时,是否很大(原始大小)?

一位朋友建议我停止提问并使用它,int 因为它有效而char无效!!但是我需要了解这里发生了什么,因为我发现我对此事的理解严重失误。您的详细答案很多寻求。谢谢。

#include<stdio.h>
#include<stdlib.h>

int main()
{
char ch;   //This is the cause of problem
//int ch;   //This solves the problem
FILE *fp,*tp;

fp=fopen("D:\\RealPlayer.exe","rb");
tp=fopen("D:\\copy.exe","wb");
if(fp==NULL||tp==NULL)
{
    printf("Error opening files");
    exit(-1);
}

while((ch=getc(fp))!=EOF)
putc(ch,tp);

fclose(fp);
fclose(tp);

}
4

2 回答 2

4

问题在于循环的终止条件。特别是变量的类型ch,结合隐式类型转换的规则。

while((ch=getc(fp))!=EOF)

getc() 返回 int - 0-255 之间的值(即 char)或 -1 (EOF)。

您将结果填充到 char 中,然后将其提升回 int 以进行比较。不愉快的事情发生,例如符号扩展。

假设您的编译器将“char”视为“signed char”(标准给了它一个选择)。

您从二进制文件中读取了 0xff (255) 的位模式 - 即 -1,表示为 char。这被提升为int,给你0xffffffff,并与EOF(也是-1,即0xffffffff)进行比较。它们匹配,你的程序认为它找到了文件的结尾,并乖乖地停止复制。哎呀!

另一个注意事项 - 你写道:

毕竟不是 int 类型的作用,即从原始文件中读取 4 个字节,然后将其写入副本文件?

这是不正确的。无论您对返回的值做什么,getc(fp) 的行为都是相同的——它从文件中读取一个字节(如果有可用的字节),并返回该值——作为一个 int。

于 2013-05-10T06:00:27.017 回答
3
int getc ( FILE * stream );

返回指定流的内部文件位置指示符当前指向的字符。成功时,将返回读取的字符(提升为 int 值)。如果您已经将 ch 定义为 int,则一切正常,但如果 ch 定义为 char,则 getc() 的返回值将被抑制回 char。

以上原因导致数据损坏和大小丢失。

于 2013-05-10T06:08:03.327 回答