Chinaunix首页 | 论坛 | 博客
  • 博客访问: 65810
  • 博文数量: 15
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 207
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-22 16:04
文章分类
文章存档

2014年(15)

分类: C/C++

2014-03-17 16:01:01

三 初始化重置函数


函数名称: memset

函数原型:void *memset(void *s, int ch, size_t n);

函数功能:在一段内存块中填充某个给定的值,是对较大的结构体或数组进行清零操作的最快方法。

参数说明:void *s — 待初始填充的内存首地址

         int ch  — 待填充的ASCII码

        size_t n — 待初始化填充的字节个数


用法


提起memset,通常都是在alloc或者new一块地址后,用来初始话置0的,这么做有什么好处呢?
void main()
{
  char * S = new char[10];
  char * S1 = "Frankie";
  memcpy(S,S1,7);//状态1—S内存地址
  memset(S,0,10);
  memcpy(S,S1,7);//状态2—S内存地址
}


我们看上述代码,在状态1时,由于没有memset初始化S对应的内存空间,当执行赋值操作后,我们可以观察S的内存状态:

这样会导致输出该字符串时由于没有00字符终止符,导致输出一堆乱码,甚至崩溃的情况出现

当我们初始化内存地址为0后,再次观察状态2S的内存地址

此时空余的地址全部都置为0,不会出现输出乱码的问题



注意事项

对于上述例子而言,由于char占用一个字节,故不会出现问题,但是如果我们初始化重置的是一个int,double等多字节数据类型时,就可能出现异常,例如

    
void main()
{
  int S1 = 10000;
  int * S = new int[2];//状态1
  int * S2 = &S1;
  memcpy(S,S2,sizeof(int)*1);//2状态
  memset(S,0,1);//3状态
  memset(S,0,sizeof(int)*2);//4状态
  memcpy(S,S2,1);//5状态
}

状态1-S内存,我们发现内存全部未初始化,这里内存地址不统一是笔者俩次实验导致的,请不要介意

状态2-S内存,我们发现完整的拷贝一个4个字节的整形后,前4个字节被有效赋值

状态3-S内存,我们只初始化置0了第一个字节

状态4-S内存,我们初始化了2个int整形即8个字节

状态5-S内存,我们只拷贝了第一个字节


这样我们就清晰的清楚了关于拷贝字节应该注意的问题了,当需要拷贝一个结构或者类时,应该sizeof该结构或者类的大小,而不应该直接按照个数来写,因为mem函数中是以字节为单位进行处理的。


PS:再补充一个利用memset清空结构体,或者清空/初始化结构体数组的方法,很实用
   
void main()
{
  struct Frankie
  {
     int age;
     char * name;
     double weight;
  };
                                                                                                                                                                                                                                                           
  struct Frankie WB ={27,"WB",75};
                                                                                                                                                                                                                                                           
  memset(&WB,0,sizeof(struct Frankie));//清空单个结构体
                                                                                                                                                                                                                                                           
  struct Frankie WBLover[100];
                                                                                                                                                                                                                                                           
  memset(WBLover,0,sizeof(struct Frankie)*100);//初始化结构体数组
                                                                                                                                                                                                                                                           
}

结果:

清空WB后效果


生成结构体数组


初始化/清空结构体数组




------------------------------------- 分界线------------------------------------

-------------------------------------------------------------------------------

函数名称:strset

函数原型:char *strset(char *s, int c);

函数功能:把字符串s中的所有字符都设置成ASK码

函数说明:不推荐使用,GCC下也没有找到该函数


原因

   一个字符串是以“/0"作为字符终止符的,但是当一个字符串未赋初始值时十不存在"/0"的,而strset会在它遇到该字符串的"/0"终止符之前一 直初始化每一位为c,这样很危险,会污染其他数据,而且一般人都会使用memset代替strset来初始化字符串,故在此仅举一反例,不做过多介绍。


void main()
{
  char * S  = new char[4]; //状态1
  char * S1 = "ABC";//状态2
                                                                      
  strset(S,0);//状态3
  strset(S,32);//状态4
  strset(S1,0);//状态5
                                                                      
                                                                      
}

状态1,S内存如下,未经初始化

状态2,S1内存如下:

状态3,strset能将s初始化为0,但是会额外将很多别的位也置零,造成“污染”

状态4,置为32无效,原因暂不清楚

状态5,直接崩溃



总结

综上比较可以发现,memset更加稳定有效,且适用范围更广,strset的功能memset均能完成,且GUN中无法找寻strset这一函数,故强烈推荐使用memset

阅读(3201) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

CU博客助理2014-05-29 10:30:11

嘉宾点评:本文很可能不是原创,在51CTO中frankiewb原创了4篇Mem系列函数与Str系列函数总结,其它博文上,武雨蓉也与frankiewb的方向不太相同,怀疑不是一个人。
http://frankiewb.blog.51cto.com/8202664/p-2