memmove详解及其模拟实现

void* memmove(void* dest, const void* src, size_t num)

返回值类型为void*,返回值为dest的起始位置,便于打印修改后的内容

功能是把 src~scr+num 中的内容拷贝到 dest~dest+num 中,虽然是move但实际上是cpy,还有一个参数是无符号整型,用于拷贝num个字节的内容,注意是字节不是元素个数

例如dest和src都是int类型,num=20,那么拷贝的是20/4 = 5个元素

实际使用:把arr2中前n个字节的内容拷贝到arr1中

memmove(arr1,arr2,n);

memmove的模拟实现:

void* my_memmove(void* dest, const void* src, size_t num) {
	//标记修改的起始位置
	void* tmp = dest;
	assert(dest && src);
	while (num--) {
		//强转成char*,按字节修改
		*(char*)dest = *(char*)src;
		//分别指向下一字节
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return tmp;
}

但是,以上代码还有一个很严重的问题,就是当dest和src的距离小于num个字节的时候,如果src<dest,可能会出现把dest修改之后,src~src+num 中的内容也被修改

例如

	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr + 2, arr, 20);

此时src指向arr[0]=1,dest指向arr[2]=3

我们想修改从dest开始的前五个元素,使其变成        1 2 1 2 3 4 5 8 9 10

而实际上变成了        1 2 1 2 1 2 1 8 9 10

原因是此时src指向了被修改过的dest

 arr[2]被改为1后,当scr指向arr[2]时,内容是1而不是原来的3了

所以当src+num<dest时,不应该从前往后修改,而是应该从后往前修改

先使src = src + num - 1,dest = dest + num - 1,分别指向末尾元素

这样第一次拷贝的结果为 1 2 3 4 5 6 5 8 9 10

此时src永远不可能指向被修改过后的dest

改进后的代码如下:

void* my_memmove(void* dest, const void* src, size_t num) {
	//标记修改的起始位置
	void* tmp = dest;
	assert(dest && src);
	//当目标地址小于源地址
	//从前往后进行修改
	if (dest < src) {
		while (num--) {
			//强转成char*,按字节修改
			*(char*)dest = *(char*)src;
			//分别指向下一字节
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	//当目标地址大于源地址
	//从dest末尾开始修改
	else {
		分别指向各自的末尾
		//dest = (char*)dest + num - 1;
		//src = (char*)src + num - 1;
		while (num--) {

			//*(char*)dest = *(char*)src;
			//dest = (char*)dest -1;
			//src = (char*)src - 1;
			
			
			//可以缩写成
			*((char*)dest + num) = *((char*)src + num);



		}
	}
	return tmp;
}

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值