c/c++的memset()函数

memset是计算机中C/C++语言函数。
将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值,
第二个值为指定的内存地址,
块的大小由第三个参数指定,
这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针。

void *memset(void *s, int ch, size_t n);
memset作用:在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。
将s中前n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
eg:一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));

第二: 过度使用memset,惧怕没有经过初始化的内存,会出现原来的残留的数据,eg:
char buffer[4];
memset(buffer,0,sizeof(char)*4);
strcpy(buffer,"123");
// "123"中最后隐藏的'\0'占一位,总长4位。
// 这里的memset是多余的. 因为这块内存马上就被全部覆盖,清零没有意义.

下面情况没有多余,因某些编译器分配空间时,内存中默认值并不为0:
char buffer[20];
memset(buffer,0,sizeof(char)*20);
memcpy(buffer,"123",3); //memcpy只是内存的拷贝,没有被处理过,所以没有“\0”结束符。
//这一条的memset并不多余,memcpy并没把buffer全部覆盖,如果没有memset,
//用printf打印buffer会有乱码甚至会出现段错误。
//如果此处是strcpy(buffer,"123");便不用memset,strcpy虽然不会覆盖buffer但是会拷贝字符串结束符“\0”

第三: 其实这个错误严格来讲不能算用错memset,但是它经常在使用memset的场合出现
int some_func(struct something *a)
{

memset(a,0,sizeof(a));

}
这里错误的原因是VC函数传参过程中的指针降级,导致sizeof(a),返回的是一个something*指针类型大小的的字节数,如果是32位,就是4字节。
也就是这里的错误用法是指针,如果要传入指针,那么就必须要传入数组的大小。

问:为何要用memset置零?memset(&Address,0,sizeof(Address));经常看到这样的用法,其实不用的话,分配数据的时候,剩余的空间也会置零的。
答:如果不清空,可能会在测试当中出现野值。你做下面的试验看看结果()

#include <iostream>
#include "string.h"
#include <afx.h>
using namespace std;
int main()
{
    char buf[5];
    CString str;
    CString str1;
    CString str2;
    memset(buf,0,sizeof(buf));
    for(int i=0;i<5;i++)
    {
        str.Format("%d",buf[i]);
        str1+=str;
    }
    str2.Format("%d",str1);
    cout<<str2<<endl;
    system("pause");
    return 0;
}


ps:这样发现没有memset,输出的都是一样的。

2、其实不然!特别是对于字符指针类型的,剩余的部分通常是不会为0的,不妨作一个试验,定义一个字符数组,并输入一串字符,如果不用memset实现清零,使用MessageBox显示出来就会有乱码(0表示NULL,如果有,就默认字符结束,不会输出后面的乱码)
eg:把数组中的元素值都设置成为字符1
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char a[5];
    memset(a,'1',5);
    for(int i=0;i<5;i++)
        cout<<a[i]<<"";
    system("pause");
    return 0;
}

下面的则是不行:
#include <iostream>
#include <cstring>
#include <windows.h>
using namespace std;
int main()
{
    int a[5];
    memset(a,1,20);//如果这里改成memset(a,1,5*sizeof(int))也可以,因为memset按字节赋值。
    for(int i=0;i<5;i++)
        cout<<a[i]<<"";
    system("pause");
    return 0;
}


问题:第一个程序可以而第二程序不可以的原因。
因为第一个程序数组a是字符型,字符型占据内存大小为1Byte,而memset是以字节为单元进行赋值的,所以输出没有问题。而第二个程序a是整形,使用memset还是按字节赋值,这样赋值完了以后,每个数组元素的值实际上是001010101即为:16843009 ,也就是并不是赋值为0.

2、不想用for,或是while循环初始化int[5],应该怎么做?(如果没有一个像memset()这样的函数初始化)
如果用memset(a,1,20);实际为与memset(a,1,5*sizeof(int)结果是一样的)就是对a指向的内存20个字节进行赋值,每个都是ASCII为1的字符去填充,转为二进制后,1就是00000001,占一个字节。一个INT元素是4字节,合一起是0000 0001,0000 0001,0000 0001,0000 0001,转化成十六进制就是0x01010101,就等于16843009,就完成了对一个INT元素的赋值了。





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值