今天看了下strcpy、memcpy、memmove的用法功能和他们的区别,以及在网上看到一些解答,在此做点总结:
1、strcpy 、memcpy、memmove 函数原型及功能
strcpy的函数原型是:char* strcpy(char* dest, const char* src);
strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容外,还会复制字符串的结束符。
memcpy的函数原型是:void *memcpy(void *dest, const char* src, size_t count);
memcpy只提供一般的内存复制,即memcpy对于需要复制的内容没有限制,因此用途更广。
memmove的函数原型是:id *memmove(void *dest,const void *src,int n)
memmove该函数和前面函数的区别是当src和desc有重复区域时,则会先将desc向后移,然后再进行拷贝操作.
2、strcpy 、memcpy、memmove 函数实现
1)strcpy的实现:(未考虑内存重叠)
<span style="color:#000099;">char *my_strcpy(char *dst,const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char *ret = dst;
while((* dst++ = * src++) != '\0')
;
return ret;
} </span>
如果注意到:
1,检查指针有效性;
2,返回目的指针des;
3,源字符串的末尾 '\0' 需要拷贝。
写出上面实现函数就不在话下。
然而这样的实现没有考虑拷贝时内存重叠的情况,下面的测试用例就能使调用my_strcp函数的程序崩溃:
char str[10]="abc";
my_strcpy(str+1,str);
然而调用系统的strcpy函数程序正常运行,打印str结果为“aabc”!可见系统strcpy函数的实现不是这样的。
strcpy的正确实现应为:
char *my_strcpy(char *dst,const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char *ret = dst;
memcpy(dst,src,strlen(src)+1);
return ret;
}
memcpy函数实现时考虑到了内存重叠的情况,可以完成指定大小的内存拷贝。
2)memcpy(考虑内存重叠)
void * My_memcpy(void *dst,const void *src,unsigned int count)
{
assert(dst);
assert(src);
void * ret = dst;
//源地址和目的地址不重叠,低字节向高字节拷贝
if (dst <= src || (char *)dst >= ((char *)src + count))
{
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else //源地址和目的地址重叠,高字节向低字节拷贝
{
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return ret;
}
3)memmove (考虑内存重叠)
<span style="color:#3333ff;">void *memmove(void *dst,const void *src,int n)
{
char *dp = (char *)dst;
char *sp = (char *)src;
assert((src!=0)&&(dst!=0)&&(n>0));//not null
//非重叠
//dp < sp
//dp > (sp+n)
if(sp>dp||(sp+n)<dp)
{
while(n--)
*(dp++) = *(sp++);
*dp = '\0';
}
else if(sp<dp)//重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
{//反向拷贝
sp += n; //helloworld
dp += n;
*dp = '\0';
while(n--)
*(--dp) = *(--sp);
}
return dst;
}</span>
4、
strcpy
、memcpy、memmove的区别:
strcpy 和 memcpy主要有以下三方面的区别:
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符串、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符串的结束符"\0”才结束,所以容易溢出。memcpy则是根据第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其它类型的数据是用memcpy。
memcpy 和 memmove 都是C语言中的库函数,在库函数 string.h中,其原型相似,它们都是从src所指向的内存中复制count个字节到dest所指内存中。并返回dest的值。
当源内存区域 和 目标内存区域无交叉重叠时,两者的结果是一样的,但如果有交叉呢?
memcpy是从src的其实部分开始复制,所以虽然第一种情况下没有问题,但如果遇到第二种情况,则会发生错误,交叉部分的src内容就会被覆盖掉了。
5、memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
编程老手们:有什么遗漏的,请留下你们的想法和补充,谢谢。