深入学习C语言中memset()函数的用法
头文件:
#include<string.h>
memset()函数用来将指定内存的前n个字节设置为特定的值,其原型为:
void*memset(void*ptr,intvalue,size_tnum);
参数说明:
ptr为要操作的内存的指针。
value为要设置的值。你既可以向value传递int类型的值,也可以传递char类型的值,int和char可以根据ASCII码相互转换。
num为ptr的前num个字节,size_t就是unsignedint。
【函数说明】memset()会将ptr所指的内存区域的前num个字节的值都设置为value,然后返回指向ptr的指针。
memset()可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。例如:
charstr[20]; memset(str,'\0',sizeof(str)-1);
【返回值】返回指向ptr的指针。
注意:参数value虽声明为int,但必须是unsignedchar,所以范围在0到255之间。
范例:
#include<stdio.h> #include<stdlib.h> #include<string.h> intmain() { //不可以声明为char*str="http://c.biancheng.net"; charstr[]="http://c.biancheng.net"; memset(str,'-',7); puts(str); system("pause"); returnEXIT_SUCCESS; }
执行结果:
-------c.biancheng.net
优化:尽量用memset将一个数组设置清零(带虚类除外),而不是通过for循环逐个置0
下面这个例子,大家可以参考:3D游戏编程大师技巧。本文其实重点是memset,原因是在工作中,用的比较多。
例如:要清空一个floatf[10000],应该用memset(f,0,sizeof(float)*10000);
而不是:for(inti=0;i<10000;++i)f[i]=0;
当然,还可以用内嵌汇编的形式:
_asm { movedi,f;//edi指向数组地的目标内存的起始处 movecx,1000/4;//循环次数或移动次数 moveax,0;//每一次移动32位数,都置0 repstosd;//移动数据 }
哈,这个准则有个前提,那就是带虚的类除外,原因是,memset将类清空,有可能将虚表也给置0了。
有可能是因为:类的创建分:栈上和堆上。
如果在栈上,那么栈对象的虚函数调用可能会在静态时确定,从而绕过虚表。所以不会出错。
但堆上就一定会出错,下面给出测试代码:
classCMemsetVirtualTest//测试带虚类,被memset为0后,虚表是否失效 { public: CMemsetVirtualTest() { memset(this,0,sizeof(CMemsetVirtualTest)); } virtualvoidNormalFun() { cout<<"test:NormalFun()虚表指针有效"<<endl; } virtual~CMemsetVirtualTest() { cout<<"test:~CMemsetVirtualTest()虚表指针有效"<<endl; } }; voidtestFun1()//测试:栈上建立的对象 { CMemsetVirtualTestCtest; Ctest.NormalFun(); } voidtestFun2()//测试:堆上建立的对象 { CMemsetVirtualTest*Ptest=newCMemsetVirtualTest(); Ptest->NormalFun();//到这里一定会暴掉 deletePtest;//如果屏蔽上句,到这里也一定会暴掉 } intmain() { CMemsetVirtualTestCtest;//测试:栈上建立的对象 Ctest.NormalFun();//测试正常: CMemsetVirtualTest*Ptest=newCMemsetVirtualTest();//测试:堆上建立的对象 Ptest->NormalFun();//到这里一定会暴掉 deletePtest;//如果屏蔽上句,到这里也一定会暴掉 }
即:
在C++中,涉及虚技术的类,他的对象内存区块中就不单纯是用户定义这个类时看上去的那些数据结构,编译器会在当中安插一些数据或代码,用来实现响应的虚技术.于是当你用memset函数时会把这些编译器安插的东西冲掉,程序执行结果变得未知.这时候如果拷贝对象C++会使用memberwise拷贝,此时编译器既拷贝用户定义的数据结构,还会对支持虚技术的相关设施进行适当的修改.
如果对象没有用到虚技术,那么就可以使用memset,就跟正常情况一样,可以逐位拷贝.