memset用法详解

作者:    更新时间:2008-1-30 13:48:36

memest原型 (please type "man memset" in your shell) 

 void *memset(void *s,  int c, size_t n); 

memset:作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法。

常见的三种错误

第一搞反了 n的位置. 

一定要记住 如果要把一个char a[20]清零一定是 memset(a, 0, 20) 
而不是 memset(a, 20,  0) 

第二过度使用memset, 我想这些程序员可能有某种心理阴影他们惧怕未经初始化的内存所以他们会写出这样的代码: 

char buffer[20]; 

memset(buffer, 0, sizeof((char)*20)); 
strcpy(buffer, "123"); 

这里的memset是多余的因为这块内存马上就被覆盖了清零没有意义

第三其实这个错误严格来讲不能算用错memset, 但是它经常在使用memset的场合出现 

int some_func(struct something *a){ 
 … 
 … 
 memset(a, 0, sizeof(a)); 
 … 

:为何要用memset置零?memset( &Address, 0, sizeof(Address));经常看到这样的用法,其实不用的话,分配数据的时候,剩余的空间也会置零的。

:1.如果不清空,可能会在测试当中出现野值。 你做下面的试验看看结果() 

char buf[5] 

CString str,str1 //memset(buf,0,sizeof(buf)) for(int i = 0i<5i ) { str.Format(“%d “,buf[i]) str1  =str  } TRACE(“%s\r\n“,str1)

2.其实不然!特别是对于字符指针类型的,剩余的部分通常是不会为0,不妨作一个试验,定义一个字符数组,并输入一串字符,如果不用memset实现清零,使用MessageBox显示出来就会有乱码(0表示NULL,如果有,就默认字符结束,不会输出后面的乱码)

:

如下demo是可以的,能把数组中的元素值都设置成字符1
i nclude <iostream>
i nclude <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;
}
而,如下程序想吧数组中的元素值设置成1,却是不可行的
i nclude <iostream>
i nclude <cstring>
using namespace std;
int main()
{
    int a[5];
    memset(a,1,5);//
这里改成memset(a,1,5 *sizeof(int))也是不可以的
    for(int i = 0;i < 5;i )
      cout<<a[i]<<"  ";
    system("pause");
    return 0;
}
问题是:

1,第一个程序为什么可以,而第二个不行,
2
,不想要用for,或是while循环来初始化int a[5];能做到吗?(有没有一个像memset()这样的函数初始化)

:

1.因为第一个程序的数组a是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。而 第二个程序a是整型的,使用memset还是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009。你 看看你输出结果是否这样? 

2.如果用memset(a,1,20);
就是对a指向的内存的20个字节进行赋值,每个都用ASCII1的字符去填充,转为二进制后, 1就是00000001,占一个字节。一个INT元素是4字节,合一起就是1000000010000000100000001,就等于 16843009,就完成了对一个INT元素的赋值了。

memset是将字符数组快速附值的一个函数,也可用它来对整型数组简单初始化,因为memset是按字节来附值的,所以对整型数组附值(不是0-1)的话是不可以的,具体看memset是如何实现的:

void* memset(void *pv, byte b, size_t size) {
byte* pb = (byte*)pv;
while(sze-- > 0) {
*pb = b;
}
return (pv);
}
上面的函数只是把每个字节都附值为b,想如果我们可以直接把若干个字节合并再填充到内存中是不是会快很多,比如说合并为long,一个整型变量(4个字节),那么就可得出下面的改进:
void* memset(void *pv, byte b, size_t size) {
byte* pb = (byte*)pv;
if (size >= sizeThreshold) {
unsigned long l;
l = (b << 8) | b;
l = (l << 16) | l;
pb = (byte*)longfill((long*)pb,l,size/4);
size %= 4;
}
while (size-- > 0) {
*pb = b;
}
return (pv);
}
其中longfill是用"long"的值填充内存快,在填完了最后一个长字节之后返回一个指向下一次所要填第一个长字的指针。sizeTreshold是设的一个阈值,确定是否用long进行填充时会提高效率。这次比上次的函数效率提高了4倍。
但是同时带来了一个新的问题,不是每个计算机中的long都占4个字节,这样就限制了程序的可移植性,因此又有了下面的进一步改进:
void* memset(void *pv, byte b, size_t size) {
byte* pb = (byte*)pv;
if (size >= sizeThreshold) {
unsigned long l;
size_t sizeS;
l = 0;
for (sizeS = sizeof(long));sizeS-->0;) {
l = (l< }
pb = (byte*)longfill((long*)pb,l,size/4);
size %= 4;
}
while (size-- > 0) {
*pb = b;
}
return (pv);
}

 

上一篇:学习C++的50条建议
下一篇:C语言变量的作用域和存储类型
站内搜索
无忧学术网 | 论文写作研究网 | 支付宝 | 电子工程师论坛 | 上海交通大学 | 东南大学 | 复旦大学 | 同济大学 | 浙江大学 | 清华大学 | 北京大学 | 承运天成 | 搜狐 | 百度 | google | 搜狗 | 雅虎 | 新浪 | 网易 | 麻省理工学院 | 中华英才网 | 无忧工作网 | 智联招聘 | 爱词霸 | 淘宝网 | 阿里巴巴 | 校友录 | 哈佛大学 | 耶鲁大学 | 腾讯 |
代写硕士论文 | 代写工程硕士论文 | 上海代写硕士论文 | 上海代写论文 | 职称论文 | 代写研究生论文 | 代写MBA论文 | 代写MPA论文 | 代写论文网