在我的项目中,我需要将共享文件复制到一个名为share的目录中。我的想法是使用fgets和fputs复制此文件的包含:
FILE *fp;
int size;
char *fileBuff
fseek(fp,0,SEEK_END );
size=ftell(fp);
printf("Size of %s: %d bytes.\n",path,size); // print correct size
fileBuff=malloc(size); // mallocate the file buffer
printf("\nsize of file buffer is %d",sizeof(fileBuff)); //always print 4!!
while(!feof(fp)){
fgets(fileBuff,size,fp); // put into file buffer
}
printf("\nsize of file buffer is %d",sizeof(fileBuff)); // also print 4!!
但是,文件缓冲区无法进行mallocated,此文件缓冲区的大小始终为4.会发生什么?
更新: 似乎有一些误解。 sizeof()如果只是为了检查文件缓冲区中是否存在任何东西。我尝试strlen(fileBuff),它总是给我1个。
答案 0 :(得分:4)
这是错误的:sizeof(fileBuff)
。这将是指针的大小,在系统上为4。
您不能使用sizeof
来“提取”malloc()
返回的内存块的大小。您不能使用任何来提取该大小,在(标准)C中根本不可能。您需要使用size
值,即malloc()
的参数。
另外,ftell()
会返回long
,而不是int
,而malloc()
和strlen()
都会失败,并且您需要考虑各种I / O调用。
在我看来,使用文件大小的缓冲区做一个简单的复制不是一个好主意;使用“合理”缓冲区(其确切的最佳大小取决于很多因素)然后在循环中重复读写对,直到您在整个文件中流式传输为止。
更新关于您的代码的更多要点:
sizeof
,但代码也在fread()
之后显示sizeof
。sizeof
“检查”缓冲区中是否有任何内容,这是不可能的;任何带有malloc()
的表达式总是在编译时 1 进行求值,它不能用于检查这样的动态事物。而且,您再次无法使用它来计算strlen()
返回的内存块的大小。strlen()
仅在文件是二进制文件并且在其最后位置包含“\ 0”时才能可靠地工作,否则您将有一个未终止的字符串并且malloc()
可能会调用未定义的行为。NULL
是否返回{{1}},如果它未能分配所请求的内存块,它将会这样做。1 除了C99中的flexible arrays,但我们忽略它。
答案 1 :(得分:2)
99位开发人员现在回答您正在使用指针的大小。我甚至不必查看代码。
答案 2 :(得分:0)
(32位)平台上指针(char *
)的大小始终为4。
您不能使用sizeof
来确定为缓冲区分配了多少内存。
要检查指针是否已分配,请检查malloc()
的返回值:
fileBuff = malloc(size);
if (fileBuff == 0) {
fprintf(stderr, "Error allocating %d bytes.\n", size);
abort();
}
答案 3 :(得分:0)
sizeof
在编译时进行评估,因为您要求sizeof
filebuf
char*
编译器计算它是malloc
4个字节(因为指针的大小是你平台的4个字节)并打印出来。您所做的sizeof
与{{1}}无关。
答案 4 :(得分:0)
除了不正确使用 sizeof()之外,你可以考虑另外两个想法:
如果只是复制文件:不要试图重新发明轮子,只需使用 system()功能并调用专为此设计的操作系统程序( cp 在unix上,在DOS / Windows上复制。
如果它是出于培训目的而你坚持自己这样做:不要尝试读取整个文件然后再写出来,而是按块读取和写入块。使用大缓冲区大小只会导致CPU缓存变得毫无价值。通常匹配文件系统缓冲区大小或它的一小部分是一个goot chunk大小,所以伪代码应该如下所示:
open input file for reading
open output file for writing
as long as read from input file BUFSIZE bytes and read bytes > 0
do write read data to output file
close input file
close output file
(并且不要忘记在每次调用I / O例程后检查I / O错误!)
最后一点:不要使用 fgets(),除非您确定它始终是纯文本文件。如果你选择使用 fread()/ fwrite(),你就会保存,即使它是一个二进制文件(而且它也更快)。