• 模拟实现C语言--memcpy函数和memmove函数


    模拟实现C语言–memcpy函数和memmove函数


    一、memcpy函数和memmove函数

    1.1 memcpy函数是什么

    void * memcpy ( void * destination, const void * source, size_t num );
    
    • 1
    1. strcpy函数是字符串拷贝函数,只能拷贝字符串,而其他类型无法使用strcpy函数拷贝
    2. 而memcpy函数属于内存拷贝函数,可以拷贝其他类型。

    1.1 memmove函数是什么

    void * memmove ( void* destination, const void * source, size_t num );
    
    • 1
    • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
    • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

    二、使用示例

    1. 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
    2. 这个函数在遇到 ‘\0’ 的时候并不会停下来
    3. 如果source和destination有任何的重叠,复制的结果都是未定义的。

    2.1 从起始位置复制

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include 
    int main()
    {
    	int i = 0;
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	memcpy(arr2, arr1, 20);
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr2[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    2.2 从任意位置复制

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include 
    int main()
    {
    	int i = 0;
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	memcpy(arr2, arr1+2, 20);
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr2[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    三、模拟实现

    3.1 模拟实现1–memcpy函数

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include 
    #include 
    
    void* my_memcpy(void* destination, const void* source, size_t num)
    {
    	void* ret = destination;
    	assert(destination);
    	assert(source);
    	/*
    	 * copy from lower addresses to higher addresses
    	 */
    	while (num--) 
    	{
    		*(char*)destination = *(char*)source;
    		destination = (char*)destination + 1;
    		source = (char*)source + 1;
    	}
    	return(ret);
    }
    int main()
    {
    	int i = 0;
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	my_memcpy(arr2, arr1+2, 20);
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr2[i]);
    	}
    	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
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    3.2 针对缺点改进的模拟实现2–memmove函数

    模拟实现1的代码有一个缺陷,就是不能进行自我拷贝

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include 
    #include 
    
    void* my_memcpy(void* destination, const void* source, size_t num)
    {
    	void* ret = destination;
    	assert(destination);
    	assert(source);
    	/*
    	 * copy from lower addresses to higher addresses
    	 */
    	while (num--)
    	{
    		*(char*)destination = *(char*)source;
    		destination = (char*)destination + 1;
    		source = (char*)source + 1;
    	}
    	return(ret);
    }
    int main()
    {
    	int i = 0;
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	my_memcpy(arr1+2, arr1, 20);
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr1[i]);
    	}
    	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
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    3.2.1 刨析原因

    在这里插入图片描述

    3.2.2 改正方法

    在这里插入图片描述

    1. 当dst指针指向的地址在src指针指向位置的右边时,这种情况的赋值应该从后向前赋值,就是12345,先让5赋值在7的位置,依次循环
      在这里插入图片描述
    2. 当dst指针指向的地址在src指针指向位置的右边时,这种情况的赋值应该从前向后赋值,34567,先将3赋值给1的位置,依次循环

    3.2.3 代码–模拟实现memmove函数

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #include 
    #include 
    
    void* my_memmove(void* destination, const void* source, size_t num)
    {
    	void* ret = destination;
    	assert(destination);
    	assert(source);
    	if (destination < source)
    	{
    		//从前向后赋值
    		while (num--)
    		{
    			*(char*)destination = *(char*)source;
    			destination = (char*)destination + 1;
    			source = (char*)source + 1;
    		}
    	}
    	//从后向前赋值
    	else
    	{
    		while (num--)
    		{
    			*((char*)destination+num)= *((char*)source+num);
    
    		}
    		
    	}
    	return ret;
    }
    
    
    int main()
    {
    	int i = 0;
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	my_memmove(arr1+2, arr1, 20);
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr1[i]);
    	}
    	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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

    3.2.4 memcpy函数和memmove函数平台问题

    目前在vs环境下,这两个函数基本没有区别,memcpy也可以解决内存重复的问题。别的平台可能还是会有这个问题

  • 相关阅读:
    【OpenCV】生成透明的PNG图像
    ESP8266-01S + Arduino 接入阿里云物联网平台
    Java之~反射,String类型模板匹配类属性方法
    【电源专题】什么是充电芯片的Shipping Mode(船运模式)
    sql 日期转为每周的第一天 周维度
    【Vue】Setup 函数的使用
    垃圾回收 - 分代垃圾回收
    国产操作系统之优麒麟安装
    c# 面试题
    拖拽表单设计器易操作、好灵活,创造高效办公!
  • 原文地址:https://blog.csdn.net/Senyu_nuanshu/article/details/132915738