• 内存函数(memcpy、memmove、memset、memcmp)你真的懂了吗?




    在这里插入图片描述

    前言

    当我们谈论内存函数时,我们在讨论什么呢?简单来说,内存函数是用于处理和操作内存的函数。这些函数在程序运行期间分配、释放和操作内存,对于程序的性能、效率和稳定性至关重要。在编程语言的发展历程中,内存函数始终占据着重要的地位,尤其是在现代编程中,它们的意义更为突出。
    本文将深入探讨内存函数的相关知识,旨在帮助读者更好地理解这一领域,并提高在现代编程中的技能。

    头文件

    🎄1.memcpy 函数

    声明

    void *memcpy(void *dest, const void *src, size_t num);
    
    • 1

    参数

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

    返回值

    • 该函数返回一个指向目标存储区 dest 的指针。

    1.1【注意事项】:

    • C 库函数 void *memcpy(void *dest, const void *src, size_t num) 从存储区 src 复制 num 个字节到存储区 dest
    • 函数memcpysrc的位置开始向后复制num个字节的数据到dest的内存位置。
    • 这个函数在遇到 '\0' 的时候并不会停下来。
    • 如果 srcdest 有任何的重叠,复制的结果都是未定义的。

    1.2【实例】

    /* memcpy example */
    #include 
    #include 
    struct {
    	char name[40];
    	int age;
    } person, person_copy;
    int main()
    {
    	char myname[] = "Pierre de Fermat";
    	/* using memcpy to copy string: */
    	memcpy(person.name, myname, strlen(myname) + 1);
    	person.age = 46;
    	/* using memcpy to copy structure: */
    	memcpy(&person_copy, &person, sizeof(person));
    	printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    🔎memcpy 的模拟实现

    //模拟实现memcpy
    #include
    #include
    
     //不重叠内存的拷贝可以使用memcpy
    void* my_memcpy(void* dest,const void* src, size_t sz)
    {
    	assert(dest && src);
    	void* ret = dest;
    	while (sz--)
    	{
    		//因为不知道要拷贝到数据类型,所以一个字节一个字节的拷贝
    		*(char*)dest = *(char*)src;
    		//强制类型转换是临时的,不能写成(char*)dest++,且++的优先级更高,void*类型指针不能加减操作
    		dest = (char*)dest + 1;
    		src = (char*)src + 1;
    	}
    	return dest;
    }
    
    int main()
    {
    	int arr1[10] = { 0 };
    	int arr2[] = { 1,2,3,4,5 };
    	my_memcpy(arr1, arr2, 20);
    	for (int i = 0; i < 5; i++)
    	{
    		printf("%d ", arr1[i]); //结果是 1 2 3 4 5
    	}
    	printf("\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    🎄2.memmove 函数

    声明

    void *memmove(void *dest, const void *src, size_t num);
    
    • 1

    参数

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

    返回值

    • 该函数返回一个指向目标存储区 dest 的指针。

    2.1【注意事项】:

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

    2.2【实例】

    /* memmove example */
    #include 
    #include 
    int main()
    {
    	char str[] = "memmove can be very useful......";
    	memmove(str + 20, str + 15, 11);
    	puts(str);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    🔎memmove 的模拟实现

    在这里插入图片描述

    //模拟实现memmove
    #include
    #include
    
    //重叠内存的拷贝,使用memmove
    void* my_memmove(void* dest, void* src, size_t sz)
    {
    	assert(dest && src);
    	void* ret = dest;
    	if (dest < src)
    	{
    		//前 -> 后
    		while (sz--)
    		{
    			*(char*)dest = *(char*)src;
    			dest = (char*)dest + 1;
    			src = (char*)src + 1;
    		}
    		/*for (int i = 0; i < sz; i++)
    		{
    			*(char*)dest = *(char*)src;
    			dest = (char*)dest + 1;
    			src = (char*)src + 1;
    		}*/
    	}
    	else
    	{
    		//后 -> 前
    		while (sz--)
    		{
    			*((char*)dest + sz) = *((char*)src + sz);
    		}
    	}
    	return ret;
    }
    
    int main()
    {
    	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    	my_memmove(arr, arr + 2, 20);
    	for (int i = 0; i < 10; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    	printf("\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    🎄3.memset 函数

    声明

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

    参数

    • ptr - - - 指向要填充的内存块。
    • value - - - 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
    • num - - - 要被设置为该值的字符数。

    返回值

    • 该值返回一个指向存储区 ptr 的指针。

    3.1【注意事项】:

    -C 库函数 void *memset(void *ptr, int value, size_t num) 复制字符 value(一个无符号字符)到参数 ptr 所指向的字符串的前 num 个字符。

    3.2【实例】

    #include 
    #include 
     
    int main ()
    {
       char str[50];
     
       strcpy(str,"This is string.h library function");
       puts(str);
     
       memset(str,'$',7);
       puts(str);
       
       return(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    🎄4.memcmp 函数

    声明

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

    参数

    • ptr1 - - - 指向内存块的指针。
    • ptr2 - - - 指向内存块的指针。
    • num - - - 要被比较的字节数。

    返回值

    • 如果返回值 < 0,则表示 ptr1 小于 ptr2
    • 如果返回值 > 0,则表示 ptr1 大于 ptr2
    • 如果返回值 = 0,则表示 ptr1 等于 ptr2

    4.1【注意事项】:

    • C 库函数 int memcmp(const void *ptr1, const void *ptr2, size_t num)) 把存储区 ptr1 和存储区 ptr2 的前 num 个字节进行比较。

    4.2【实例】

    代码1:

    /* memcmp example */
    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    代码2:

    #include 
    #include 
    
    int main()
    {
    	char str1[15];
    	char str2[15];
    	int ret;
    
    	memcpy(str1, "abcdef", 6);
    	memcpy(str2, "ABCDEF", 6);
    
    	ret = memcmp(str1, str2, 5);
    
    	if (ret > 0)
    	{
    		printf("str1 大于 str2\n");
    	}
    	else if (ret < 0)
    	{
    		printf("str1 小于 str2\n");
    	}
    	else
    	{
    		printf("str1 等于 str2\n");
    	}
    
    	return(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    🔥今天的分享就到这里, 如果觉得博主的文章还不错的话, 请👍三连支持一下博主哦🤞

  • 相关阅读:
    如何使用Vuex来管理应用程序的状态?
    GBase 8d的特性-可扩展性
    STM32F103 USART1串口使用DMA接收不定长数据和DMA中断发送
    【SparkSQL】数据的加载和保存、项目实战
    go-zero直连与etcd服务注册中心
    C++11智能指针shared_ptr应用于继承结构
    Nodejs系列之模块加载机制
    taro 兼容支付宝小程序和微信小程序<六>-- 自定义密码或验证码输入框组件的input 自动获取焦点(ios支付宝小程序怎么隐藏input的光标)
    《从零开始大模型开发与微调 :基于PyTorch与ChatGLM》简介
    为何在校学习的网络系专业的知识难以在社会工作中派上用场?
  • 原文地址:https://blog.csdn.net/2201_75743654/article/details/133436210