【C/C++】memset方法的误区

1、前言

memset 做为对内存初始化的函数,仍是有很多坑和误区的,今天就来对这个函数做一个总结。避免后期使用不当踩入坑。数组

2、函数做用

最简单的调用就是将一个数组清零,代码以下:函数

const int maxn = 1024;
int a[maxn];
memset(a, 0, sizeof(a)); // 结果:a[0]=a[1]=a[...]=0;
  • 这里 sizeof(a) = maxn * 4 = 4096;
  • 表示的是将 数组首地址 a 开始日后的 4096 个字节,都设置为 0;

3、效率对比

直接调用 memset 接口清零 和 调用循环进行清零,进行一个测试后以下:测试

对长度为 10000000 的数组,执行100次调用;
模式 memset for
debug 375ms 2156ms
release 343ms 329ms
  • 由于 release 版本会作各类优化,编译器发现重复执行无效逻辑就会跳过,因此不太好造数据测试,研究时间效率的时候仍是参考 debug 版本(固然,软件发布的时候确定用的是 release 版本)。
  • memset 不管从时间效率,仍是代码整洁来看都是因为 for 循环的,固然也带来了一些容易引发误解的地方。

4、误区总结

一、按字节设置

  • memset 实现原理是根据字节来设置的,好比对于字节数组char a[100],将全部字节都设置为5,就能够调用:
 memset(a, 5, sizeof(a));
  • 可是,对于int b[100],也采用这种方法,就会致使错误:
memset(b, 5, sizeof(b));
  • 获得 b 数组中元素的值为 84215045;
  • 为何呢?
  • 咱们把这个数组转换成二进制,获得:
  • ( 00000101 00000101 00000101 00000101 ) 2 (00000101 \ 0000 0101 \ 0000 0101 \ 0000 0101)_2 (00000101  00000101  00000101  00000101)2
  • 由于 i n t int int 占据了 4 4 4 个字节,把每一个字节都设置成了5,因此最后转成十进制就变成了 84215045;
  • 同理,当类型是 short(二字节整数),或者 long long(八字节整数)都会有相似问题,总结表格以下:
memset值 char short int long long
0 0 0 0 0
-1 -1 -1 -1 -1
5 5 1285 84215045 361700864190383365
  • 表格中,只有0 和 -1是正常的,由于 0 的二进制表示中,全部位都为0;-1 的二进制表示中,全部位都为 1;
  • 特别的,当须要设置的数,对应类型的每一个字节都是同一个数的时候,也能够采用 memset,好比:int 类型的 252645135(十六进制表示为:0x0f0f0f0f);

二、设置的值只有最低字节有效

memset(a, 0x05ffffff, sizeof(a));
memset(a, 0xffffff05, sizeof(a));
memset(a, 0xffffff08, sizeof(a));
memset(a, 0x12345678, sizeof(a));
  • 设置值的时候,只会采用最低的字节做为赋值用,通俗的讲,就是以上四句话调用,等价于:
memset(a, 0xff, sizeof(a));
memset(a, 0x05, sizeof(a));
memset(a, 0x08, sizeof(a));
memset(a, 0x78, sizeof(a));

三、堆内存不可直接 sizeof 取首地址

在堆上申请了一个数组空间,而且想要给它初始化,调用以下:优化

const int maxn = 1024;
int *p = new [maxn];
memset(p, 0, sizeof(p));
  • 这里进入了另外一个误区,由于 p p p 在这里虽然是数组首地址,可是它扮演的角色更多的,实际上是个指针,因此在进行 sizeof 运算符操做的时候,取得的值并非 4096,而是指针的大小;
  • 32位机子上,指针大小为4,;64位机子上,指针大小为 8;
  • 正确作法是:
const int maxn = 1024;
int *p = new [maxn];
memset(p, 0, maxn * sizeof(int));

四、传参数组不可直接 sizeof 取首地址

  • 对传参为数组的数据进行 memset,调用以下:
void fun(int a[maxn])
{    
    memset(a, 0, sizeof(a));
}
  • 这里调用一样是错误的,由于当数组做为传参的时候,这里的 a 已经退化为指针,因此一样不能用 sizeof 数组首地址来取大小;
  • 正确作法是:
void fun(int a[maxn]) 
{    
    memset(a, 0, maxn * sizeof(int));
}
  • 固然,当传参是结构体指针的时候也是如此;

参考于:CSDN- 英雄哪里出来https://blog.csdn.net/WhereIsHeroFrom/article/details/111660632.net

相关文章
相关标签/搜索