您的位置:首页 > 运维架构 > Linux

【原创】memset和memcpy用法总结 分类: Linux --- C Linux --- C++ 2014-11-11 20:45 70人阅读 评论(0) 收藏

2014-11-11 20:45 721 查看
【原创】memset和memcpy用法总结

需要的头文件

在C中 <string.h>

在C++中<cstring>

memset(将一段内存空间填入某值)

相关函数 bzero,swab

表头文件 #include<string.h>

定义函数 void * memset (void *s ,int c, size_t n);

函数说明 memset()会将参数s所指的内存区域前n个字节以参数c填入,然后返回指向s的指针。在编写程序时,若需要将某一数组作初始化,memset()会相当方便。

返回值 返回指向s的指针。

附加说明 参数c虽声明为int, 但必须是unsigned char ,所以范围在0到255之间。

范例

#include <string.h>
main()
{
char s[30];
memset (s,’A’,sizeof(s));
s[30]=’\0’;
printf(“%s\n”,s);
}
执行

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

memcpy(拷贝内存内容)

相关函数 bcopy,memccpy,memcpy,memmove,strcpy,strncpy

表头文件 #include<string.h>

定义函数 void * memcpy (void * dest ,const void *src, size_t n);

函数说明 memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束‘\0‘而结束。

返回值 返回指向dest的指针。

附加说明 指针src和dest所指的内存区域不可重叠。

范例

#include<string.h>
main()
{
char a[30]=”string (a)”;
char b[30]=”string\0string”;
int i;
strcpy(a,b);
printf(strcpy():”);
for(i=0;i<30;i++)
printf(“%c”,a[i]);
memcpy(a,b,30);
printf(“\nmemcpy() :”);
for(i=0;i<30;i++)
printf(“%c”,a[i]);
}
执行

strcpy() : string a )

memcpy() : string string

当心memset的陷阱

参考链接:http://www.cnblogs.com/chenyg32/p/3289068.html

示例代码:

#include <iostream>
#include <cstring>
using namespace std;

void f(int s[5]){
memset(s, 0, sizeof(s));
}

int main()
{
int s[] = {1,2,3,4,5};
f(s);
for (int i = 0; i < 5; ++i)
cout << s[i] << ' ';
cout << endl;
system("pause");
}
上面这段程序的输出竟然是:0 2 3 4 5

就是说memset只清空了第一个元素!

所以将数组当作参数传递的时候,不要用memset,memset应该和数组在同一块代码区。

Why?

静态数组作为参数传入某个函数的时候,就会退化成指针,也就是该数组的首地址,其数组的长度信息就丢掉了,这就是在这个语境下退化的概念。

这也是为什么在将数组作为参数传递时,同时要将数组的长度也一并传入的原因。

当然除了再传递一个数组长度给函数这种方法来防止数组退化成指针之外,还有1种方法是使用数组的引用,加多一个'&'就可以了。

所以这个不是memset的错……memset对不起。

顺便提一提以前的小陷阱,用memset将int,bool数组置为0是可以的,但置为1是不行的;将char数组置为'1'是可以的。

Why?

memset是按字节赋值,char是字节,int是4个字节,所以char是可以的,int是不行的。(可以输出sizeof(char), sizeof(int)查看)

memset第一个参数是开始填充的地址,第二个参数是填充的byte,第三个参数要填充的字节数(注意是字节数)。

比如置为1,那么赋值的结果应该是00000001000000010000000100000001,为16843009。

通俗的讲,就是将1变为00000001,然后从数组头开始,每8位填充一个00000001,直到填充的次数等于第三个参数。最后如果是int,那就按Int的位数取出来,得到16843009。

看示例代码:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
int s[] = {1,2,3,4,5};
memset(s, 1, sizeof(s));
for (int i = 0; i < 5; ++i)
cout << s[i] << ' ';
cout << endl;
system("pause");
}
程序的输出是:16843009 16843009 16843009 16843009 16843009

如果是置为0,那么全部都是0,所以还是0

因为0全部都是0,所以可以,那么全部是f呢,答案就是-1,全部初始化为-1也是可以的。

memset另一个参考链接

http://www.cnblogs.com/lebronjames/archive/2010/07/04/1770987.html

功 能

  将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,  其返回值为指向S的指针。用 法

  void *memset(void *s, int ch, unsigned n);

程序示例

  #include <string.h>
  #include <stdio.h>
  #include <memory.h>
  int main(void)
  {
  char buffer[] = "Hello world\n";
  printf("Buffer before memset: %s\n", buffer);
  memset(buffer, '*', strlen(buffer) );
  printf("Buffer after memset: %s\n", buffer);
  return 0;
  }
  输出结果:

  Buffer before memset: Hello world

  Buffer after memset: ***********

  编译平台:

  Microsoft Visual C++ 6.0

  也不一定就是把内容全部设置为ch指定的ASCII值,而且该处的ch可为int或者其他类型,并不一定要是char类型。例如下面这样:

  int array[5] = {1,4,3,5,2};
  for(int i = 0; i < 5; i++)
  cout<<array[i]<<" ";
  cout<<endl;
  memset(array,0,5*sizeof(int));
  for(int k = 0; k < 5; k++)
  cout<<array[k]<<" ";
  cout<<endl;
  输出的结果就是:

  1 4 3 5 2

  0 0 0 0 0

  后面的表大小的参数是以字节为单位,所以,对于int或其他的就并不是都乘默认的1(字符型)了。而且不同的机器上int的大小也可能不同,所以最好用sizeof()。

  

  要注意的是,memset是对字节进行操作,所以上述程序如果改为

  int array[5] = {1,4,3,5,2};
  for(int i = 0; i < 5; i++)
  cout<<array[i]<<" ";
  cout<<endl;
  memset(array,1,5*sizeof(int));// 注意 这里与上面的程序不同
  for(int k = 0; k < 5; k++)
  cout<<array[k]<<" ";
  cout<<endl;
  输出的结果就是:

  1 4 3 5 2

  16843009 16843009 16843009 16843009 16843009

  为什么呢?

  因为memset是以字节为单位就是对array指向的内存的5个字节进行赋值,每个都用ASCII为1的字符去填充,转为二进制后,1就是00000001,占一个字节。一个INT元素是4字节,合一起就是00000001000000010000000100000001,就等于16843009,就完成了对一个INT元素的赋值了。

  所以用memset对非字符型数组赋初值是不可取的!

  例如有一个结构体Some x,可以这样清零:

  memset( &x, 0, sizeof(Some) );

  如果是一个结构体的数组Some x[10],可以这样:

  memset( x, 0, sizeof(Some)*10 );

memset函数详细说明

  1。void *memset(void *s,int c,size_t n)

  总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。

  2。例子

  main(){
  char *s="Golden Global View";
  clrscr();
  memset(s,'G',6);//貌似这里有点问题//
  printf("%s",s);
  getchar();
  return 0;
  } 
 【应该是没有问题的,字符串指针一样可以,并不是只读内存,可以正常运行】

  3。memset() 函数常用于内存空间初始化。如:

  char str[100];

  memset(str,0,100);

  4。memset()的深刻内涵:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘memset(a, '\0', sizeof(a));

  memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:

  char a[100], b[50];

  memcpy(b, a, sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。

  strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:

  char a[100], b[50];

  strcpy(a,b);

  如用strcpy(b,a),要注意a中的字符串长度(第一个‘\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。

  5.补充:某人的一点心得

  memset可以方便的清空一个结构类型的变量或数组。

  如:

  struct sample_struct
  {
  char csName[16];
  int iSeq;
  int iType;
  };
  //对于变量
  struct sample_strcut stTest;
  //一般情况下,清空stTest的方法:
  stTest.csName[0]='\0';
  stTest.iSeq=0;
  stTest.iType=0;
  //用memset就非常方便:
  memset(&stTest,0,sizeof(struct sample_struct));
  //如果是数组:
  struct sample_struct TEST[10];
  //则
  memset(TEST,0,sizeof(struct sample_struct)*10);


原文链接:

/article/1574931.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐