深入浅出C语言内存函数

本文将深入解析C语言中的内存操作函数!

                                                                                                                 ——— 既然选择了,就一定坚持下去


1.memcpy使⽤和模拟实现

        

1.memcpy的简介

1.参数分析:    

            

        void * memcpy ( void * destination, const void * source, size_t num )

         

参数一:void * destination  (指向目标数组,其中要复制内容,类型转换为 void* 类型的指针

 

参数二:const void * source(指向要复制数据的源,类型转换为 const void* 类型的指针。

 

参数三:size_t num  (要复制的字节数

 

返回类型:void*              

  

 

 2.功能分析:

        

        将 source 指向的位置的 num 个字节值直接复制到 destination 指向的内存块

  

3.注意事项:

        

        为避免溢出,指向目标数组和源参数的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。

         

 2.memcpy的简单使用

    memcpy函数包含在<string.h>这个头文件中,在使用的时候需要包含改头文件进引用,改函数仅仅针对与内存块未重叠时,进行复制操作。

          

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 5 * sizeof(int));
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

         

        

3.memcpy的模拟实现

        

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);  //防止指针为空
	void* ret = dest;  //由于目标指针会发生改变,保存初始指针
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

        

 2.memmove的使用和模拟实现

1.memmove的简介

1.参数分析:    

            

        void * memmove ( void * destination, const void * source, size_t num )

         

参数一:void * destination  (指向目标数组,其中要复制内容,类型转换为 void* 类型的指针

 

参数二:const void * source(指向要复制数据的源,类型转换为 const void* 类型的指针。

 

参数三:size_t num  (要复制的字节数

 

返回类型:void*   

 

2.函数功能 :

 

        将 source 指向的位置的 num 个字节值复制到 destination 指向的内存块。复制过程如同使用一个中间缓冲区,允许目标位置和源位置重叠。

 

3.注意事项:

        内存块重叠的理解:例如要将arr数组的前五个(1,2,3,4,5)复制到(3,4,5,6,7),这就会出现内存块的重叠,如果仅仅用memcpy的函数复制方式就会出现赋值异常。

  

        通过memcpy复制五个元素的异常结果。

          

 2.memove的简单使用

通过memmove就可以解决上述问题,代码如下:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("操作前的arr数组\n");
	for (int i = 0; i < 10; i++)
	{		
		printf("%d ", arr[i]);
	}

	memmove(arr + 2, arr, 5 * sizeof(int));

	printf("\n操作后的arr数组\n");
	for (int i = 0; i < 10; i++)
	{		
		printf("%d ", arr[i]);
	}
	return 0;
}

          

3.memmove的实现

        为了解决memcpy实现不了内存块重叠的问题,我们需要通过实现memmove,来进行处理内存块重叠。

 实现思路:

针对于这种情况source的地址小于destination的情况,我们通过正序复制,会导致异常       

基于这种情况要将(1,2,3,4,5)正序复制到(3,4,5,6,7)会出现覆盖的情况,那就我们可以通过逆序的方式进行复制,将5->7   4->6   3->5   2->4   1->3 这样就不会出现覆盖的情况。

  

  

针对于这种情况source的地址小于destination的情况,我们通过逆序复制,会导致异常

基于这种情况要将(3,4,5,6,7)逆序复制到(1,2,3,4,5)会出现覆盖的情况,所以我们可以通过正序的方式进行复制,将3->1  4->2 5->3  6->4  7->5 这样就不会出现覆盖的情况。

 

针对不同的情况我们可以通过不一样的复制方式:

 

①当destination<=source的时候我们可以通过正序的方式进行复制。

 

②当destination>source的时候我们可以通过逆序的方式进行复制。

        

#include<stdio.h>
#include<assert.h>
#include<string.h>

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;

	if (dest <= src)
	{
		//按照从前向后的顺序进行拷贝
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		src = (char*)src + num - 1;
		dest = (char*)dest + num - 1;
		//按照从后向前的顺序进行拷贝
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}

		/*
			while (num--)
			{
				*((char*)dest+num) = *((char*)src+num);
			}
		*/
	}
	return ret;
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("操作前的arr数组\n");
	for (int i = 0; i < 10; i++)
	{		
		printf("%d ", arr[i]);
	}

	my_memmove(arr + 2, arr, 5 * sizeof(int));

	printf("\n操作后的arr数组\n");
	for (int i = 0; i < 10; i++)
	{		
		printf("%d ", arr[i]);
	}
	return 0;
}

         

3.memset的使用

1.memset的简介

1.参数分析

 

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

 

参数一:要填充的内存块指针待赋值的指针)

    

参数二:要设置的值。该值作为 int 传递,但函数使用该值的无符号字符转换来填充内存块。

参数三:要设置为该值的字节数。

 

2.函数功能:

 

        将 ptr 指向的内存块的第一个 num 字节设置为指定的值(解释为 unsigned char )。

         

2.memset的简单使用

#include<stdio.h>
#include<assert.h>
#include<string.h>


int main()
{

	char arr1[] = "hello world";
	memset(arr1, 'x', 5);
	printf("%s\n", arr1);

	//int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
	//memset(arr2, 1, 10 * sizeof(int));//将每个字节都设置为1

	//for (int i = 0; i < 10; i++)
	//{
	//	printf("%d ", arr2[i]);
	//}
	return 0;
}

         

4.memcmp的使用

1.memcmp的简介

1.函数参数:

        int memcmp ( const void * ptr1, const void * ptr2, size_t num );

 

参数一:待比较的指针1。

 

参数二:待比较的指针2

 

参数三:要比较的字节数

 

返回值:

2.函数功能:

         

        比较由 ptr1 指向的内存块的前 num 个字节与由 ptr2 指向的内存块的前 num 个字节,如果它们全部匹配则返回零,如果不匹配则返回一个非零值,表示哪个更大。

3.注意事项:

                

请注意,与 strcmp 不同,该函数在找到空字符后不会停止比较。

         

2.memcmp的简单使用

void test4()
{
	//memcmp 每个字节的比较

	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);

}

既然看到这里了,就给笔者一个三连吧,谢谢!!!

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值