三 初始化重置函数


函数名称: 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的内存状态:

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset

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

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_02

此时空余的地址全部都置为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内存,我们发现内存全部未初始化,这里内存地址不统一是笔者俩次实验导致的,请不要介意

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_03

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_04

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_05

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_06

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_07


这样我们就清晰的清楚了关于拷贝字节应该注意的问题了,当需要拷贝一个结构或者类时,应该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后效果

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_08


生成结构体数组

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_09


初始化/清空结构体数组

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_10




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

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

函数名称: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内存如下,未经初始化

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_11

状态2,S1内存如下:

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_12

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_13

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

Mem系列函数与Str系列函数总结 (三)  memset 与 strset_memset; strset_14

状态5,直接崩溃



总结

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