Error[8]: Undefined offset: 41, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录


📘前言

本文章会详解C语言进阶内容,有关内存 *** 作函数(memcpy,memmove,memcmp,memset)的使用说明、API文档该类函数原型以及模拟实现内存函数


📗 一、memcpy(内存拷贝) 📖 1. 函数说明

首先我们从API文档中搜索memcpy查看一下该函数的原型

可以看出该函数有三个参数,那么这三个参数的作用分别是什么呢?

该函数的实现思路是将把源头数据const void * source拷贝到目标数据void * destination里去,最后一个参数size_t num则代表需要拷贝多少个字节,这个函数在遇到'strcpy'的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。

那么它与字符串函数void*有什么区别呢?

我们可以看出memcpy的函数参数的返回类型是num,所以memcpy不考虑你拷贝的数据是何种类型,都可以将原指针指向的空间传入dest个字节数拷贝到*src指针处;而strcpy的参数是已经被写死了,传入的类型必须是char类型数据,实现较为单一。

简单的实现一下该函数

我们定义了两个int类型的数组,接着使用memcpy,如果想拷贝五个元素到arr2数组中去,因为int类型数组一个元素大小占4个字节,要拷贝五个元素,则第三个参数给的是20个字节。


📖 2. 模拟实现

因为是模拟实现,所以我们需要设计的函数返回类型,参数个数,参数类型都要与其一致。

由于数组元素要考虑字节数,所以就涉及到大小端的问题,这里我们以小端为例:1 在内存中十六进制是 0x 00 00 00 01,小端存储是低位放在低地址,高位放在高地址。

如果我们需要向上面图解所示,将arr1数组的元素按照每一个字节拿到arr2数组中,一共拿20个字节,我们怎么才能做到一个一个字节拿出来呢?

首先我们需要对指针解引用 *** 作,把*dest的内容放到char*中去,因为一次要拷贝一个字节,我们可以直接强制类型转化成char*类型就可以访问一个字节了。接着继续往后访问,还需要强制类型转化成num类型再+1让指针往后走;该 *** 作需要执行的次数取决于参数while的取值所以这里用void*循环,随着每一次的 *** 作,num–,直到num为0循环结束。最后该函数设计的时候返回的是一个void* res指针,所以我们可以在循环 *** 作前,先定义一个dest用来存放最初始的return res;程序结束,memcpy就可以了。


💡 3. 运行图示:


📗二、memmove 📖 1. 函数说明

由上述memcpy函数想到一个问题,我们在拷贝的时候能不能从同一个数组里,将arr1数组前五个元素拷贝到,从3开始3,4,5,6,7这个位置上,理想结果arr1数组应该是{1,2,1,2,3,4,5,8,9,10}这样的结果可事实真是如此吗?接着我们调试,从监视里观察arr数组的元素

从图中可以看出arr1数组运行完的结果与预期的有所差异,下标为2到下标为6的元素变成了1,2,1,2,1了!

由图所示从同一个数组中不同位置进行拷贝 *** 作的时候,原空间和目标空间有重叠的时候,拷贝过程中已经将目标空间的数据已经覆盖掉了,后续再进行拷贝 *** 作的时候,拷贝的数据已经不是原空间的数据了。

如果是如上情况(src在dest的右边并有重叠部分)就得从4开始拷贝,从前向后拷贝。反之如果src在dest的左边,则需要从后向前拷贝,如果没有重叠部分,从前向后or从后向前都是可行的,因为没有数据不会在拷贝前被覆盖了

所以我们不能使用memmove函数进行在同一个数组里进行内存拷贝!这时候就要用到另一个内存函数memcmp


📖 2. 模拟实现

此时我们只需思考从后往前拷贝时,应该如何实现

从图中可知,src是

从调试窗口中可以看出,结果与开始的预测相同

模拟完成

💡 3. 运行图示:


📗三、memcmp 📖 1. 函数说明

函数原型

memcmp是比较内存区域ptr1和ptr2的前num个字节,比较的是内存大小,*注如果两个字符串相同且num值大于字符串长度的话,不会在\0出停下程序,会继续往后进行比较,直到达到num次数

📖 2. 函数的功能(主要作用)

strcmpmemset函数功能相似,只不过是可以对所有类型都进行一个字节一个字节的比较,逐字节比较内存的大小。
返回值有三种情况

‘< 0’ :"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 < “参数ptr2”;(VS编译器下返回值为 -1)
‘= 0’: "参数ptr1"与"参数ptr2"内存大小相等;(VS编译器下返回值为 0)
‘> 0’:"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 > “参数ptr2”。(VS编译器下返回值为 1)

举 ‘>0’ 一例说明:


📗三、memset 📖 1. 函数说明

函数原型

以字节为单位来设置值
参数分别为:
1 . 一个指向需要被修改的内存空间的地址
2 . 指定修改的内容(int类型)
3 . 需要修改的字节数

📖 2. 函数的功能(主要作用)

num函数的作用:在指向的内存空间的前int value个字节内容修改成所指定的[+++]的内容,有些类似于memcpy的工作原理。
图示说明


📝 总结

以上就是有关C语言进阶的内容,内存 *** 作函数部分的模拟实现和函数使用说明及方法。
希望该篇文章对大家的学习有所帮助,期待与大家共同进步,持续更新中…
点个关注点个赞👍吧!
💗🤍💕💖

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
C语言——内存 *** 作函数_C_内存溢出

C语言——内存 *** 作函数

C语言——内存 *** 作函数,第1张

文章目录
  • 📘前言
  • 📗 一、memcpy(内存拷贝)
    • 📖 1. 函数说明
    • 📖 2. 模拟实现
    • 💡 3. 运行图示:
  • 📗二、memmove
    • 📖 1. 函数说明
    • 📖 2. 模拟实现
    • 💡 3. 运行图示:
  • 📗三、memcmp
    • 📖 1. 函数说明
    • 📖 2. 函数的功能(主要作用)
  • 📗三、memset
    • 📖 1. 函数说明
    • 📖 2. 函数的功能(主要作用)
  • 📝 总结


📘前言

本文章会详解C语言进阶内容,有关内存 *** 作函数(memcpy,memmove,memcmp,memset)的使用说明、API文档该类函数原型以及模拟实现内存函数


📗 一、memcpy(内存拷贝) 📖 1. 函数说明

首先我们从API文档中搜索memcpy查看一下该函数的原型

可以看出该函数有三个参数,那么这三个参数的作用分别是什么呢?

该函数的实现思路是将把源头数据const void * source拷贝到目标数据void * destination里去,最后一个参数size_t num则代表需要拷贝多少个字节,这个函数在遇到'strcpy'的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。

那么它与字符串函数void*有什么区别呢?

我们可以看出memcpy的函数参数的返回类型是num,所以memcpy不考虑你拷贝的数据是何种类型,都可以将原指针指向的空间传入dest个字节数拷贝到*src指针处;而strcpy的参数是已经被写死了,传入的类型必须是char类型数据,实现较为单一。

简单的实现一下该函数

我们定义了两个int类型的数组,接着使用memcpy,如果想拷贝五个元素到arr2数组中去,因为int类型数组一个元素大小占4个字节,要拷贝五个元素,则第三个参数给的是20个字节。


📖 2. 模拟实现

因为是模拟实现,所以我们需要设计的函数返回类型,参数个数,参数类型都要与其一致。

由于数组元素要考虑字节数,所以就涉及到大小端的问题,这里我们以小端为例:1 在内存中十六进制是 0x 00 00 00 01,小端存储是低位放在低地址,高位放在高地址。

如果我们需要向上面图解所示,将arr1数组的元素按照每一个字节拿到arr2数组中,一共拿20个字节,我们怎么才能做到一个一个字节拿出来呢?

首先我们需要对指针解引用 *** 作,把*dest的内容放到char*中去,因为一次要拷贝一个字节,我们可以直接强制类型转化成char*类型就可以访问一个字节了。接着继续往后访问,还需要强制类型转化成num类型再+1让指针往后走;该 *** 作需要执行的次数取决于参数while的取值所以这里用void*循环,随着每一次的 *** 作,num–,直到num为0循环结束。最后该函数设计的时候返回的是一个void* res指针,所以我们可以在循环 *** 作前,先定义一个dest用来存放最初始的return res;程序结束,memcpy就可以了。


💡 3. 运行图示:


📗二、memmove 📖 1. 函数说明

由上述memcpy函数想到一个问题,我们在拷贝的时候能不能从同一个数组里,将arr1数组前五个元素拷贝到,从3开始3,4,5,6,7这个位置上,理想结果arr1数组应该是{1,2,1,2,3,4,5,8,9,10}这样的结果可事实真是如此吗?接着我们调试,从监视里观察arr数组的元素

从图中可以看出arr1数组运行完的结果与预期的有所差异,下标为2到下标为6的元素变成了1,2,1,2,1了!

由图所示从同一个数组中不同位置进行拷贝 *** 作的时候,原空间和目标空间有重叠的时候,拷贝过程中已经将目标空间的数据已经覆盖掉了,后续再进行拷贝 *** 作的时候,拷贝的数据已经不是原空间的数据了。

如果是如上情况(src在dest的右边并有重叠部分)就得从4开始拷贝,从前向后拷贝。反之如果src在dest的左边,则需要从后向前拷贝,如果没有重叠部分,从前向后or从后向前都是可行的,因为没有数据不会在拷贝前被覆盖了

所以我们不能使用memmove函数进行在同一个数组里进行内存拷贝!这时候就要用到另一个内存函数memcmp


📖 2. 模拟实现

此时我们只需思考从后往前拷贝时,应该如何实现

从图中可知,src是

从调试窗口中可以看出,结果与开始的预测相同

模拟完成

💡 3. 运行图示:


📗三、memcmp 📖 1. 函数说明

函数原型

memcmp是比较内存区域ptr1和ptr2的前num个字节,比较的是内存大小,*注如果两个字符串相同且num值大于字符串长度的话,不会在\0出停下程序,会继续往后进行比较,直到达到num次数

📖 2. 函数的功能(主要作用)

strcmpmemset函数功能相似,只不过是可以对所有类型都进行一个字节一个字节的比较,逐字节比较内存的大小。
返回值有三种情况

‘< 0’ :"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 < “参数ptr2”;(VS编译器下返回值为 -1)
‘= 0’: "参数ptr1"与"参数ptr2"内存大小相等;(VS编译器下返回值为 0)
‘> 0’:"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 > “参数ptr2”。(VS编译器下返回值为 1)

举 ‘>0’ 一例说明:


📗三、memset 📖 1. 函数说明

函数原型

以字节为单位来设置值
参数分别为:
1 . 一个指向需要被修改的内存空间的地址
2 . 指定修改的内容(int类型)
3 . 需要修改的字节数

📖 2. 函数的功能(主要作用)

num函数的作用:在指向的内存空间的前int value个字节内容修改成所指定的的内容,有些类似于memcpy的工作原理。
图示说明


📝 总结

以上就是有关C语言进阶的内容,内存 *** 作函数部分的模拟实现和函数使用说明及方法。
希望该篇文章对大家的学习有所帮助,期待与大家共同进步,持续更新中…
点个关注点个赞👍吧!
💗🤍💕💖

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/2990638.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存