memset
memset是内存初始化函数
最简单的调用是将一个数组清零
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。
memset常见误区
- memset实现原理是根据字节来设置的
比如对于字节数组char a[100]
,将所有字节都设置为5,就可以调用:
memset(a, 5, sizeof(a));
但是,对于int b[100]
,也采用这种方法,就会导致错误:
memset(b, 5, sizeof(b));
得到 b 数组中元素的值为 84215045;
为什么?
我们将b数组元素转换成二进制得到:
( 00000101 00000101 00000101 00000101) 2
因为int占据了4个字节,memset是按字节来设置的,把每个字节都设置成了5,转换成十进制就成了84215045
- 堆内存不可直接 sizeof 取首地址
在堆上申请了一个数组空间,并且想要给它初始化,调用如下:
const int maxn = 1024;
int *p = new [maxn];
memset(p, 0, sizeof(p));
这里进入了另一个误区,因为 p 在这里虽然是数组首地址,但是它扮演的角色更多的其实是个指针,所以在进行 sizeof 运算符操作的时候,取得的值并不是 4096,而是指针的大小;
正确做法是:
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));
}
当然,当传参是结构体指针的时候也是如此。