函数原型
void * memmove ( void * destination, const void * source, size_t num );
功能
从指针source指向的地址复制num个字节到destination所指向的内存块, 返回destination指向的地址
特点
允许destination和source内存块重叠, 函数不检查NULL终止字符
destination和source指针指向的对象类型不影响函数,函数的执行结果总是二进制拷贝注意
为了避免溢出,source和destination指向的数组大小至少为num字节
函数源码
ENTRY(memmove)
pushl %esi
pushl %edi
movl 12(%esp), %edi ;edi存储destination
movl 16(%esp), %esi ;esi存储source
movl 20(%esp), %ecx ;ecx存储num
pushl %edi ;与popl %eax对应,使返回值为destination
testl %ecx, %ecx
jz 2f ;如果num为0则退出
cmpl %esi, %edi
jb 1f ;如果souce地址小于destination地址,
addl %ecx, %esi ;则使用rep movsb指令从esi指向的地址复制ecx个字节到edi指向的地址
decl %esi
addl %ecx, %edi ;否则将destination和source跳转到要复制的最后一个字节
decl %edi ;使用std指令改变地址增长方向,反向复制num个字节
std
1:
rep
movsb
2:
cld
popl %eax
popl %edi
popl %esi
ret
END(memmove)
C语言实现
void *memmove(void *destination, const void *source, size_t num)
{
assert((destination!=NULL) && (source!=NULL));
char *des;
const char *src;
size_t n;
des = (char *)destination;
src = (const char *)source;
if (des > src)
{
for (n = 0; n < num; ++n)
*des++ = *src++;
}
else
{
des = des + num - 1;
src = src + num - 1;
for (n = 0; n < num; ++n)
*des-- = *src--;
}
return destination;
}
经典用法
从数组中删除元素
int a[5] = {1,2,3,4,5};
memmove(a+1,a+3,2*sizeof(a[0]));
// a[5] = {1,4,5,4,5};