• C语言《超详细解析内存函数》


    内存函数

    一、memcpy函数

    (1)、函数内容解析

    memcpy指的是C使用的内存拷贝函数。
    函数原型:

    在这里插入代码片void * memcpy(void * de, const void * sr, size_t num)
    
    • 1

    (一)、参数:
    de:指向用于存储内容的目标数组,类型强制转换为void指针。
    sr:指向要复制的数据源,类型强制转换为void
    指针
    n:要被复制的字节数。
    为什么要使用void* ,当传参的时候我们不知道传的是什么类型,而void就像一个垃圾桶,可以接受任何的类型,例如整型,浮点型,字符型等。
    (二)、返回值:
    该函数返回一个指向目标存储区de的指针。
    (三)、功能:
    从源sr所指的内存地址起始位置开始拷贝n个字节到目标de所指的内存地址的起始位置中。
    (四)、所需头文件:
    C语言;#include
    (五)、函数实现:
    如图:在这里插入图片描述
    运行结果:
    在这里插入图片描述

    (2)、memcpy模拟实现

    在这里插入图片描述
    模拟函数内容解析:
    1、把源a2内容6个数拷贝到目标a1数组中,也即24个字节。2、模拟函数中的参数和原型中保持一致,使之更规范。
    3、在模拟函数中,先把目标数组起始地址存到一个变量中,便于我们返回,因为函数类型是void*,变量类型也是void*。
    4、在while循环中,我们需要一个字节一个字节去拷贝,要把源地址和目标地址转换为字符型,它是一个字节,之后再解引用进行拷贝,一个字节拷完之后还需拷下一个字节,所以先转为字符型指针再加1,直到num字节数为0停止。
    模拟函数运行结果如下:
    在这里插入图片描述

    (3)、memcpy函数说明

    1、sr和de所指的内存区域可能重叠,但是如果sr和de所指的内存区域重叠,那么这个函数不能确保sr所在重叠区域在拷贝之前不被覆盖。这个问题我们可以接下来介绍的memmove去解决重叠区域。
    2、如果目标de本身已有数据,执行memcpy后,将覆盖原有数据,如要追加数据,则每次执行完后,要将目标数组地址增加到你要追加数据的地址。

    二、memmove函数

    (1)、memmove内容解析

    memmove也是用于拷贝字节,memmove和memcp内容基本一样,但用法有些不同。
    (1)、函数实现:
    如图:
    在这里插入图片描述

    运行结果:
    在这里插入图片描述

    (2)、memmove模拟实现

    在这里插入图片描述

    在这里插入图片描述
    模拟函数内容解析:
    1、把源a数组从起始地址开始5个数(20个字节)拷贝到目标a数组地址从a+2处也即使第三个元素开始的数组中。
    2、模拟函数中的参数类型和原型中保持一致,使之更规范。
    3、在模拟函数中,先把目标数组起始地址存到一个变量中,便于我们返回,因为函数类型是void*,变量类型也是void*。并断言一下指针变量便于找错。
    4、在while循环中,存在一些细节:
    当在自身数组里拷贝时候:
    (1)、当目标地址de小于源地址sr时:我们把sr中的内容从前往后一个字节一个字节去拷贝,如果从前往后,会被覆盖掉产生五个数中最后两个数字的循环。所以先要把源地址和目标地址转换为字符型,它是一个字节,之后再解引用进行拷贝,一个字节拷完之后还需拷下一个字节,所以先转为字符型指针再加1,直到num字节数为0停止。
    (2)、当目标地址de大于源地址时:我们要把sr中的内容从后往前拷贝,如果从前往后就如上例,会出现 1,2,1,2,1,2,1,8,9,10,会把3,4,5覆盖掉,所以从后往前拷贝,在while循环中,把de和sr先转换为char*1字节,再加上已经减去1的num再解引用就是五个数中最后一个字节,止到num减为0结束。
    模拟函数运行结果如下:
    在这里插入图片描述

    (3)、memmove函数说明

    如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改,但是当目标区域和源区域没有重叠,则和memcpy函数功能相同

    三、memcmp函数

    (1)、memcmp函数内容

    该函数是比较字节的
    函数原型:
    int memcmp ( const void * ptr1,const void * ptr2,size_t num );
    (一)、参数:
    ptr1:指向内存块的指针。
    ptr2:指向内存块的指针
    num:要被比较的字节数
    (二)、功能:
    比较内存区域ptr11和ptr2前num个字节
    (三)、返回值:
    如果返回值<0,则表示ptr1小于ptr2.
    如果返回值>0,则表示ptr2小于ptr1
    如果返回值=0,则表示ptr1等于ptr2
    (四)、头文件:
    #include
    (五)、函数实现:
    在这里插入图片描述
    运行结果:
    在这里插入图片描述

    (2)、memcmp模拟实现

    在这里插入图片描述
    模拟函数内容解析:
    1、比较a1数组和a2数组前9个字节的大小。
    2、模拟函数参数类型和原型保持一致,使用void* ,当传参的时候我们不知道传的是什么类型,而void就像一个垃圾桶,可以接受任何的类型,例如整型,浮点型,字符型等。
    3、因为是一个字节一个字节比较,用for循环,循环num次即可。
    4、在for循环嵌套一个if语句来判断是否相等,先把ptr1和ptr2转为一字符类型,即char*类型,再解引用比较大小,如果相等就++,如果不能直接返回两个字节的差值。
    5、当num循环完之后,说明比较的字节内容都相等,就返回0。
    模拟函数运行结果如下:
    在这里插入图片描述

    (3)、memcmp函数说明

    它是按字节比较的,传过去多少字节,就比较多少。对比是以字节为单位,strcmp时以字符为单位。

    四、memset函数

    (1)、 memset内容解析

    它是C语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值。
    函数原型:
    void* memset(void* s,int ch,int n)
    (一)、参数
    s:是数组首元素地址
    ch:被设的值
    n;被设值的字节个数
    (二)、返回值:
    该函数返回一个指向s的指针。
    (三)、功能
    将某一块内存中的内容全部设置为指定的值。
    (四)、头文件
    #include
    (五)、函数实现:
    在这里插入图片描述
    运行结果:
    在这里插入图片描述

    (2)、memset模拟实现

    在这里插入图片描述

    模拟函数内容解析:
    1、把数组前12个字节初始化为0
    2、断言一下指针,方便检查在第几行出错
    3、用热帖保存s的起始地址
    4、用一个for循环,循环num次停止,在里面设置值,把s先强制转换char*进行赋ch,之后指针再加1即可。
    模拟函数运行结果如下:
    在这里插入图片描述

    (3)、memset函数说明

    memset函数按字节对内存进行初始化,所以它不能用它将int数组初始化为0或-1之外的其他值。

    五、模拟库函数实现源代码

    (1)、memcpy源代码

    #include//模拟实现memcpy内存函数
    void* my_memcpy(void* de,void* sr,int num)
    {
    	void* ret = de;
    	while (num--)
    	{
    		*(char*)de = *(char*)sr;
    		de = (char*)de + 1;
    		sr = (char*)sr + 1;
    	}
    	return ret;
    }
    int main()
    {
    	int a1[9] = { 1,2,3};
    	int a2[6] = { 4, 5, 6, 7, 8, 9 };
    	my_memcpy(a1, a2, 24);
    	for (int i= 0; i < 6; i++)
    	{
    		printf("%d", a1[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

    (2)、memmove源代码

    在这里插入代码片#include<stdio.h>
    #include//模拟实现memmove
    void* my_memmove(void* de,void* sr,int num)
    {
    	assert(de&&sr);
    	void* ret = de;
    	if (de < sr)
    	{
    		while (num--)
    		{
    			*(char*)de = *(char*)sr;
    			de = (char*)de + 1;
    			sr = (char*)sr + 1;
    		}
    	}
    	else if (de>sr)
    	{
    		while (num--)
    		{
    			*((char*)de + num) = *((char*)sr + num);
    		}
    	}
    	return ret;
    }
    int main()
    {
    	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    	my_memmove(a+2 , a, 20);
    	for (int i = 0; i < 10; i++)
    	{
    		printf("%d ", a[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

    (3)、memcmp源代码

    在这里插入代码片#include<stdio.h>//模拟实现memcmp函数
    int my_memcmp(const void * ptr1, const void * ptr2, int num)
    {
    	for (int i = 0; i < num; i++)
    	{
    		if (*((char*)ptr1) == *((char*)ptr2))
    		{
    			ptr1 = (char*)ptr1 + 1;
    			ptr2= (char*)ptr2 + 1;
    		}
    		else
    		{
    			return *((char*)ptr1) - *((char*)ptr2);
    		}
    	}
    	return 0;
    }
    int main()
    {
    	int a1[] = {1,2,3};
    	int a2[] = {1,2,4};
    	int ret = memcmp(a1, a2,9);
    	printf("%d\n", ret);
    	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

    (4)、memset源代码

    在这里插入代码片#include<stdio.h>//memset模拟实现
    #include
    void* my_memset(void* s, int ch, int n)
    {
    	assert(s);
    	void* ret = s;
    	for (int i = 0; i < n; i++)
    	{
    		*((char *)s) = ch;
    			s = (char*)s + 1;
    	}
    	return ret;
    }
    int main()
    {
    	int a[] = { 1, 2, 3, 4, 5, 6 };
    	my_memset(a, 0, 12);
    	for (int i = 0; i < 6; i++)
    	{
    		printf("%d ", a[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
  • 相关阅读:
    python基于django的智能短视频推荐系统 nodejs 前后端分离
    前端八股文-Promise解决问题,基本用法,存在缺点,then,catch,finally,all,race,前端性能优化,全过程,如何学习
    软件缺陷与软件测试定义
    CSS3新增选择器(属性选择器、结构伪类选择器、伪元素选择器)
    关于redisson的序列化配置
    opencv videocapture
    什么是JUC
    Java-设计Bird/Fish类
    hackRF--初步实战(ubuntu环境)
    14.HTML和CSS 02
  • 原文地址:https://blog.csdn.net/m0_59292239/article/details/126850132