Chinaunix

标题: memset的恐慌 [打印本页]

作者: k8king    时间: 2011-09-23 12:20
标题: memset的恐慌
很惭愧,学习,使用C语言已经有一段时间了,但是对于memset的使用仍然是云里雾里,我确实惧怕没有初始化的内存,所以有的时候宁可滥用,以求得心理上的安慰。
有没有大牛能够讲下心得,帮我等开启一盏指路明灯?
举个例子
  1.         memset(tmpbuf,0,sizeof(tmpbuf));
  2.         while(fread(tmpbuf,1,sizeof(tmpbuf),fp)!=0)
  3.         {
  4.                 printf("tmpbuf = %s\n",tmpbuf);
  5.                 memset(tmpbuf,0,sizeof(tmpbuf));
  6.         }
复制代码
这两处memset都必要吗?可以去掉吗?
代码也跑过,似乎有与没有问题不大,可能我测试的不够完全,请大家释疑。
作者: ljmmail    时间: 2011-09-23 12:24
可以去掉的, 这是仅仅是一个比较保险的写法, 某些人的开发风格问题。
作者: zylthinking    时间: 2011-09-23 12:24
充分利用 fread 的返回值则不需要, 象你这样利用, 则需要
作者: mirnshi    时间: 2011-09-23 13:48
本帖最后由 mirnshi 于 2011-09-23 13:49 编辑
可以去掉的, 这是仅仅是一个比较保险的写法, 某些人的开发风格问题。
ljmmail 发表于 2011-09-23 12:24


这种写法,是不能去掉的。fread的buffer区,不追加字符串结束符。用fread读字符串,其实比较奇怪的。
作者: net_robber    时间: 2011-09-23 14:47
sizeof(tmpbuf)是多大???
作者: mirnshi    时间: 2011-09-23 14:53
回复  mirnshi
这个是我例子举得有误,抱歉了。不过我有个疑问,假如fread读取两次,第一次buff长度为5, ...
k8king 发表于 2011-09-23 14:47


你的buffer大小变化的?fread是按照你给定的buffer大小读的,最多读取整个buffer的长度,如果小了,或者是文件尾或者有其他异常了
作者: k8king    时间: 2011-09-23 15:31
本帖最后由 k8king 于 2011-09-23 15:33 编辑

回复 5# net_robber
测试数据如下(包含空行)
  1. 123456
  2. asd


  3. AAA AAA AAA
  4. CCC
  5. ssdd
  6. @

  7. .
复制代码
代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. int main(int argc,char*argv[])
  5. {
  6.         char tmpbuf[7];
  7.         int i;
  8.         FILE *fp;
  9.         if((fp = fopen(argv[1],"r"))==NULL)
  10.         {
  11.                 exit (-1);
  12.         }
  13.         while(fread(tmpbuf,1,sizeof(tmpbuf),fp)!=0)
  14.         {
  15.                 printf("%s",tmpbuf);
  16.         }
  17.         fclose(fp);
  18.        
  19.         printf("###################\n");
  20.        
  21.         if((fp = fopen(argv[1],"r"))==NULL)
  22.         {
  23.                 exit (-1);
  24.         }
  25.         memset(tmpbuf,0,sizeof(tmpbuf));
  26.         while(fread(tmpbuf,1,sizeof(tmpbuf),fp)!=0)
  27.         {
  28.                 printf("%s",tmpbuf);
  29.                 memset(tmpbuf,0,sizeof(tmpbuf));
  30.         }
  31.         fclose(fp);
  32. }
复制代码
两种方法确实没看到什么区别,这有点奇怪。
作者: k8king    时间: 2011-09-23 15:41
还是要用memset
作者: KBTiller    时间: 2011-09-23 17:34
1.没用
2.用不用memset(),代码都有问题
作者: k8king    时间: 2011-09-23 22:02
回复 9# KBTiller
请指点一二,拜谢!
作者: KBTiller    时间: 2011-09-24 10:09
回复 10# k8king


    首先,代码其实等价于

  1.         
  2.         while ( memset(tmpbuf,0,sizeof(tmpbuf)) ,
  3.                   fread(tmpbuf,1,sizeof(tmpbuf),fp)!=0 )
  4.                {
  5.                   printf("tmpbuf = %s\n",tmpbuf);
  6.                }
复制代码


memset(tmpbuf,0,sizeof(tmpbuf))的作用是把tmpbuf数组中的每个字节都填充为(unsigned char)0
fread()函数是把从fp指向的输入流中读取字符
如果不发生没读入的情况(fread(tmpbuf,1,sizeof(tmpbuf),fp)!=0)
那么tmpbuf数组的每个字符都被重写了一遍
从这里能够看出memset(tmpbuf,0,sizeof(tmpbuf))不必要性
(谁也不会 int n; n=0;scanf("%d",&n); 吧?)
由于tmpbuf数组的每个字符都被重写了一遍
无法保证在tmpbuf数组中存在'\0'
这样
printf("tmpbuf = %s\n",tmpbuf);
的结果就毫无保证
因而我认为memset(tmpbuf,0,sizeof(tmpbuf))非但不必要,而且是错误的

使用fread(tmpbuf,1,sizeof(tmpbuf),fp)读数据,我和前面4楼看法一样,感觉莫名其妙
我认为怎么也应该用fgets(),而且fp应该是"r"方式打开的而不是"rb"方式打开的
作者: k8king    时间: 2011-09-24 18:24
回复 11# KBTiller


    是printf带来的对使用意义上的分歧,这个是我举例有误,printf这个位置如果换成fwrite(tmpbuf,1,i,fpo);怎么样?其实想要实现文件合并的功能,因为觉得memset可能会有问题,所以一开始写printf来测试读取的值。这里解释一下为什么用fread,只要适当扩大tmpbuf,以fread的方式读取,可以减少读取的次数。
作者: ezioma    时间: 2011-09-24 19:09

  1.        int read_bytes = 0;
  2.        memset(tmpbuf,0,sizeof(tmpbuf));
  3.        while((read_bytes = fread(tmpbuf,1,sizeof(tmpbuf) - 1,fp))!=0)
  4.         {
  5.                 tmpbuf[read_bytes] = '\0';
  6.                 printf("tmpbuf = %s\n",tmpbuf);
  7.         }
复制代码

作者: 毛xx总理    时间: 2011-09-24 19:47
ezioma 发表于 2011-09-24 19:09



   
作者: KBTiller    时间: 2011-09-24 20:21
回复  KBTiller
是printf带来的对使用意义上的分歧,这个是我举例有误,printf这个位置如果换成fwrite(tmpbuf,1,i,fpo);怎么样?其实想要实现文件合并的功能,因为觉得memset可能会有问题,所以一开始写printf来测试读取的值。这里解释一下为什么用fread,只要适当扩大tmpbuf,以fread的方式读取,可以减少读取的次数。k8king 发表于 2011-09-24 18:24


那我觉得memset()还是没有意义
如果我没理解错的话
我觉得你想要的大概是下面的样子

do {
   size_t  size   ;
   size  =  fread(tmpbuf,1,sizeof(tmpbuf),fp) ;
   fwrite( tmpbuf , 1 ,  size  ,fpo);
}
while(没读到结尾);
作者: k8king    时间: 2011-09-24 21:04
本帖最后由 k8king 于 2011-09-24 21:05 编辑

回复 15# KBTiller

嗯,基本上和你想的一样,但是因为无法预知最后一次能够读到多少字节,觉得最后一次读取的值如果没有memset的话,,很有可能会和倒数第二次的值会在一起,出现混乱,所以使用了memset,测试的时候发现假如文件中间出现空行的话,文件结尾有时候就会很奇怪。
作者: KBTiller    时间: 2011-09-24 21:06
回复  KBTiller

嗯,基本上和你想的一样,因为无法预知最后一次能够读到多少字节,觉得最后一次读取的值 ...
k8king 发表于 2011-09-24 21:04



    size  =  fread(tmpbuf,1,sizeof(tmpbuf),fp) ;
这个不就知道最后一次读了多少字节了吗
作者: KBTiller    时间: 2011-09-24 21:09
回复 16# k8king


    The fread function returns the number of elements successfully read, which may be less than nmemb if a read error or end-of-file is encountered.
作者: k8king    时间: 2011-09-24 21:27
回复 18# KBTiller


    啊,果然!15楼的时候你就表达了这个意思了,我忽略了!受教育了。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2