当前位置:首页 » 《随便一记》 » 正文

C语言内存函数介绍以及实现

29 人参与  2023年05月03日 08:09  分类 : 《随便一记》  评论

点击全文阅读


目录

前言

一:内存拷贝函数

(1)memcpy( )函数

(2)memove( )函数

二:内存比较函数

三:内存设置函数


前言

本文介绍的函数的函数声明都在头文件string.h中。

一:内存拷贝函数

(1)memcpy( )函数

函数声明:void* memcpy(void* dest,const void* src,size_t num)

作用:把一片内存空间的字节拷贝到另一片内存空间。

函数参数的意义:

①dest指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

②src指向要复制的数据源,类型强制转换为 void* 指针。同时我们只是拷贝这一片空间的数据到目标空间而不是修改,所以用const进行修饰。

③num(无符号整型)表示要拷贝的字节数。

函数返回值:

函数调用结束后为了方便我们判断是否拷贝成功,我们把目标地址返回。

调用:

baf1c0b67d0f4a0f9dc9ba1ef0414a43.png

 模拟实现的思路:

要一个个字节进行交换,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到

一个字节进行交换,然后继续迭代,通过传入的num来控制循环。

注意:

①*(char*)dest++是不可以的,因为++的优先级大于强制类型转换,对空类型++是非法的。

②*((char*)dest)++在C里面是可以的,但是在C++里面不可以,因为强制转换产生的临时变量在C++里面不能进行++操作。

代码:

//内存拷贝函数(拷贝不重叠)加测试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;}int main(){int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[5] = { 0 };//int类型占4个字节//交换20个字节就是交换数组前5个元素my_memcpy(arr2, arr1, 20);for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;}

(2)memove( )函数

函数声明:void* memove(void* dest,const void* src,size_t num)

作用:用来拷贝重叠的两片内存空间。

函数参数的意义:

①dest指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

②src指向要复制的数据源,类型强制转换为 void* 指针。同时我们只是拷贝这一片空间的数据到目标空间而不是修改,所以用const进行修饰。

③num(无符号整型)表示要拷贝的字节数。

函数返回值:

函数调用结束后为了方便我们判断是否拷贝成功,我们把目标地址返回。

调用:

133c1699ed2d4f36a954c449a04c9dca.png

为什么要把重叠的情况单独拿出来?我们看下面这种情况:

323d8d67ba654969a2976fed54675d91.png

 这种目标地址大于源地址的情况,如果要拷贝的数据只有2和3,是没有问题的。

但是如果要拷贝2,3,4,5的话,我们希望的情况的1,2,3,2,3,4,5,8。但实际上我们进行第一次拷贝的时候就已经把4给覆盖掉了。

要防止后面的数据被提前覆盖,我们可以从后面往前拷贝,即先把5赋给7,然后4赋给6,这样就很好的解决了数值被覆盖的问题。

模拟实现的思路:

①进行分类,如果目标地址小于源地址,前向后拷贝;如果目标地址大于或者等于源地址,后向前拷贝。

②一个个字节进行交换,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到

一个字节进行交换,然后继续迭代,通过传入的num来控制循环。

 

代码:

//内存拷贝函数(重叠)和测试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{while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;}int main(){int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };//把0,1,2拷贝到3,4,5my_memmove(arr1+4, arr1, 20);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;}

二:内存比较函数

memcmp( )函数

函数声明:int memcmp(const void* ptr1,const void* ptr2,size_t num)

作用:用来比较两片内存空间,这里的比较不是比较数据,而是一个个字节进行比较,遇到不同的字节就判断大小。

函数参数的意义:

①ptr1和ptr2指向待比较的目标数组,类型强制转换为 void* 指针。同时我们只是比较而不是修改,所以用const进行修饰。

②num(无符号整型)表示要比较的字节数。

函数返回值:

如果两片空间的每一个字节都相同就返回0,如果前面的大就返回大于0的数,前面的小就返回小于0的数。

调用:

a216d1c615094d72a00f503f153872e6.png

模拟实现的思路:

①一个个字节进行比较,用num来控制循环次数。

②如果不相同就直接返回两个字节的差值。

③如果循环结束就代表前num个字节相同,返回0。

代码:

//内存比较函数和测试int my_memcmp(const void* ptr1, const void* ptr2, size_t num){//断言,不能传空指针进来assert(ptr1 && ptr2);while (num--){if (*(char*)ptr1 != *(char*)ptr2)return *(char*)ptr1-*(char*)ptr2;//如果相等,迭代ptr1 = (char*)ptr1 + 1;ptr2 = (char*)ptr2 + 1;}return 0;}int main(){int arr1[10] = { 0,1,2,3,4,5,6,7,8,1 };int arr2[20] = { 0,1,2,3,4,5,6,7,8,10 };int ret = my_memcmp(arr1, arr2, 40);printf("%d ", ret);return 0;}

三:内存设置函数

memset( )函数

函数声明:void* memset(void* ptr,int value,size_t num)

作用:用来初始化内存空间(以字节为单位)。

函数参数的意义:

①ptr指向待初始化的目标数组,类型强制转换为 void* 指针。

②value表示要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。

重点讲一下value这个参数,要知道我们是对每一个字节进行初始化,一个字节是无法存储像1000这样较大的数据的,这种情况初始化是取1000最后的一个字节进行初始化。

比如传入1000和232初始化的结果是一致的。

③num(无符号整型)表示要初始化的字节数。

函数返回值:

函数调用结束后为了方便我们判断是否初始化成功,我们把目标地址返回。

调用:

bf2aa9a5bffd4ad4b8702a8d4aac102f.png

 718260aa09624902ab4e2ba356792d2d.png

模拟实现的思路:

一个个字节进行初始化,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到

一个字节进行初始化,然后继续迭代,通过传入的num来控制循环。

代码:

//内存设置函数(初始化)void* my_memset(void* ptr, int value, size_t num){//断言,不能传空指针进来assert(ptr);void* ret = ptr;while (num--){*(char*)ptr = value;(char*)ptr = (char*)ptr + 1;}return ret;}int main(){int arr[10] = { 0 };//只认最后一个字节(输入1000和232结果是一样的)my_memset(arr, 232, 40);for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}return 0;}

 


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/60313.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1