内存函数————手撕memove/memcpy等函数,轻松搞懂!

目录

1.  memcpy函数的使用和模拟实现

 手撕memcpy函数

2.  memmove函数的使用和模拟实现

手撕memmove函数

3. memset函数的使用

4. memcmp函数的使用


   

 

        这是一张面试的截图,提到的这两个函数,就是我们本章要学习的内存函数中的两个函数。可以看得出,内存函数还是比较重要的,接下来,我将带大家轻松搞懂C语言中的所有内存函数,展示其内部源代码,帮助大家在面试中也能手撕内存函数!点赞+收藏我们开始。

1.  memcpy函数的使用和模拟实现

void * memcpy ( void * destination, const void * source, size_t num );
    
//destination : 目的地内存的起始地址

//source : 源地址内存的起始地址

//num : 要拷贝的字节个数

        我们来铺垫一下,什么是void*呢,这是泛型,可以接受任意数据类型的指针,但使用时必须强转。

        这里为什么使用void* 就显然意见了,你不知道要接受什么样的数据类型,那就使用泛型,可以接受所有的数据类型。

        那const是什么意思呢,显然我们是将源地址内容放到目的内存中,源内存不需要修改,就用const修饰,避免了误操作。

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr1, arr2, sizeof(arr2));
	size_t sz = sizeof(arr2) / sizeof(arr2[0]);

	printf("arr2[] = ");
	for (size_t i = 0;i < sz;i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");

	char c1[6] = { 0 };
	char c2[] = "hello";
	memcpy(c1,c2,sizeof(c2));
	printf("c1[] = %s",c1);
	return 0;
}

  

         手撕memcpy函数

void* my_memcpy(void* dest, void* src, size_t num)
{
    assert(dest && src);
	void* ret = dest;    
	while(num)	//size_t 类型没有负数 !!!
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;	//(char*)dezst++ 程序报错
		src  = (char*)src + 1;
		num--;
	}
	return ret;
}

        这里我们有一个问题,我们可不可以将同一块内存空间中不同位置的内容进行拷贝?例如,将int arr[10] ={1,2,3,4,5,6,7,8,9,10},将1,2,3,4,5放到3,4,5,6,7的位置上呢?

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

        

        显然这不是我们想要的结果,为什么,这是因为内存地址重叠了,我们实现的memmove函数是从前往后拷贝的,3,4,5早就被拷贝成1,2了怎么可能往后拷贝呢。所以可以得出结论,memcpy函数可以处理不重叠的内存之间的数据拷贝。

        那如果我们想要将重叠的内存进行数据拷贝,就要使用memmove函数了。

2.  memmove函数的使用和模拟实现

        

void * memmove ( void * destination, const void * source, size_t num );
    
//destination : 目的地内存的起始地址

//source : 源地址内存的起始地址

//num : 要拷贝的字节个数

        我们用memmove函数使用看看我们上面所讲的重叠内存拷贝。

        其实我们很容易想出问题所在,既然我们从前往后拷贝有问题,那从后往前呢,这样不是就不会覆盖了吗。其实就这么简单。

        但是,我们要注意,不是所有场景都是从前往后,也不是所有场景都是从后往前。

                 

        我们要根据不同场景灵活运用,memmove函数就是这么样实现的,它会进行判断。

        手撕memmove函数

        

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest > src)
	{
		while (num--)	
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	else
	{
		while (num--)	
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;	
			src = (char*)src + 1;		
        }
	}
	return ret;
}

3. memset函数的使用

void * memset ( void * ptr, int value, size_t num );

        memset函数是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "xxxxxxxxxx";
	memset(arr, 'h', 5);
	printf("%s", arr);
}

         

4. memcmp函数的使用

 int memcmp ( const void * ptr1, const void * ptr2, size_t num );
        比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
        返回值如下:
#include <stdio.h>
#include <string.h>

int main ()
{
  char buffer1[] = "DWgaOtP12df0";
  char buffer2[] = "DWGAOTP12DF0";

  int n;

  n=memcmp ( buffer1, buffer2, sizeof(buffer1) );

  if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
  else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
  else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);

  return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋刀鱼的滋味@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值