需要的头文件:#include <string.h>
原型:
extern void* memcpy(void *dest, const void *src, size_t n);
//If copying takes place between objects that overlap, the behavior is undefined
功能:由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
注意:
1.source和destin所指的内存区域可以重叠,但是如果source和destin所指的内存区域重叠,那么这个函数并不能够确保source所在重叠区域在拷贝之前被覆盖。而使用memmove可以用来处理重叠区域。函数返回指向destin的指针。
2.strcpy和memcpy主要有以下3方面的区别。
2.1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2.2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
2.3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
注意:source和destin都不一定是数组,任意的可读写的空间均可。
4.标准库函数提供了地址重叠时的内存拷贝函数:memmove()因为memmove()函数把源字符串拷贝到临时buf里,然后再从临时buf里写到目的地址,增加了一次不必要的开销,但是可以解决内存重叠拷贝问题。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void *memcpy(void *dst,const void *src,size_t size);
int mian(int argc,char *argv[])
{
char buf[100]="abcdefgh";
Memcpy(buf+2,buf,5);//memcpy(buf+2,buf,5);
printf("%s\n",buf+2);
}
//如果函数的参数可以是任意类型指针,那么应声明其参数为void *
void *Memcpy(void *dst,const void *src, size_t size)
{
char *psrc;
char *pdst;
if(dst == NULL|| src == NULL) return NULL;
if((src<dst)&&(char*)src+size>(char*)dst)//src和dst内存重叠,则自后向前拷贝
{
psrc = (char*)src+size-1;
pdst = (char*)dst+size-;
while(size--)
{
*pdst-- = *psrc--;
}
}
else
{
psrc = (char*)src;
pdst = (char*)dst;
while(size--)
{
*pdst++ = *psrc++;
}
}
return dst;
}
PS:size_t 类型定义在cstddef.h头文件中,该文件是C标准库的头文件stddef.h的C++版。它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
在C++中,size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型,因为C/C++标准只定义最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。当然,有些是编译器或系统已经给定义好的。经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。
关于void* :如果函数的参数可以是任意类型指针,那么声明其参数为void*;
典型的如内存操作函数memcpy和memset的函数原型分别为:
void * memcpy(void *dest, const void *src, size_t size);
void * memset ( void * buffer, int c, size_t size );
这样任何类型的指针都可以传入memcpy和memset中,真实体现了内存操作函数的意义,yinwei