我是靠谱客的博主 机智人生,最近开发中收集的这篇文章主要介绍带你手写memcpy和memmove,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

什么是memcpy

**C 库函数 void *memcpy(void str1, const void str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1


这是memcpy()函数的声明
void *memcpy(void *str1, const void *str2, size_t n)


参数

  • str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
  • n – 要被复制的字节数。

实现my_memcpy

void* my_memcpy(void* buf1, void* buf2, size_t num)
{
	assert(buf1); //当buf1为空指针的时候显示错误信息,并且中止程序
	assert(buf2);
	void* ret = buf1; //定义一个void*变量记录buf1的初始地址
	while (num--)  //这段循环就是逐字节复制,将buf2的地址赋给buf1
	{
		*((char*)buf1) = *((char*)buf2); 
		buf1 = (char*)buf1 + 1; //因为空指针不能进行自增自减操作,所以先转成char*指针,然后进行自增。
		buf2 = (char*)buf2 + 1; //因为是地址赋值,所以必须得是逐字节,所以转成char*类型。
	}
	return ret; //返回buf1的初始地址
}
void test05()
{
	char arr[20] = "zxc";
	char arr2[] = "abc";
	char* tmp = (char*)my_memcpy(arr, arr2, 3); //因为返回的是个void*,所以必须强转成(char*)
	printf("%s", tmp); //结果为abc
}

memcpy有一种特殊情况

void*的指针变量

void*的指针变量就是一个什么都能接收的指针,用户不可能就只传特定的一个指针变量给你,就像你写个**void* my_memcpy(int* buf1, int* buf2, size_t num)**这里面写的是int指针,那么用户想传个char或者结构体指针变量呢,难道你还重写一个吗?所以这时候就要用到void*指针,什么都可以接收,可以在函数体内强转成任何类型的指针,非常好用,具体使用场景可以看看qsort()函数的模拟实现,这里就不多讲了。

什么是memmove

**C 库函数 void *memmove(void str1, const void str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。


这是memmove()函数的声明

void *memmove(void *str1, const void *str2, size_t n)


参数

  • str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
  • n – 要被复制的字节数。

实现my_memcpy

void* my_memmove(void* buf1, const void* buf2, size_t num)
{
	assert(buf1);
	assert(buf2);
	void* ret = buf1;
	if (buf1 < buf2)
	{
		while (num--)
		{
			*((char*)buf1) = *((char*)buf2);
			buf1 = (char*)buf1 + 1;
			buf2 = (char*)buf2 + 1;
		}
		return ret;
	}
	else
	{
		while (num--)
		{
			*((char*)buf1 + num) = *((char*)buf2 + num);
		}
	}
	return ret;
}
void test05()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	char arr2[] = "abc";
	my_memmove(arr + 5, arr + 3, 16);
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
}

memmove其实才是真正的memcpy,我先来解释一下这段代码

	if (buf1 < buf2)
	{
		while (num--)
		{
			*((char*)buf1) = *((char*)buf2);
			buf1 = (char*)buf1 + 1;
			buf2 = (char*)buf2 + 1;
		}
		return ret;
	}
	else
	{
		while (num--)
		{
			*((char*)buf1 + num) = *((char*)buf2 + num);
		}
	}
	return ret;


memmove才是真男人

最后

以上就是机智人生为你收集整理的带你手写memcpy和memmove的全部内容,希望文章能够帮你解决带你手写memcpy和memmove所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部