本文章会详解C语言进阶内容,有关内存操作函数(memcpy,memmove,memcmp,memset)的使用说明、API文档该类函数原型以及模拟实现内存函数
可以看出该函数有三个参数,那么这三个参数的作用分别是什么呢?
该函数的实现思路是将把源头数据const void * source
拷贝到目标数据void * destination
里去,最后一个参数size_t num
则代表需要拷贝多少个字节,这个函数在遇到'\0'
的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。
那么它与字符串函数
strcpy
有什么区别呢?
我们可以看出memcpy的函数参数的返回类型是void*
,所以memcpy不考虑你拷贝的数据是何种类型,都可以将原指针指向的空间传入num
个字节数拷贝到dest
指针处;而strcpy的参数是已经被写死了,传入的类型必须是char类型数据,实现较为单一。
简单的实现一下该函数
我们定义了两个int类型的数组,接着使用memcpy,如果想拷贝五个元素到arr2数组中去,因为int类型数组一个元素大小占4个字节,要拷贝五个元素,则第三个参数给的是20个字节。
由于数组元素要考虑字节数,所以就涉及到大小端的问题,这里我们以小端为例:1 在内存中十六进制是 0x 00 00 00 01,小端存储是低位放在低地址,高位放在高地址。
如果我们需要向上面图解所示,将arr1数组的元素按照每一个字节拿到arr2数组中,一共拿20个字节,我们怎么才能做到一个一个字节拿出来呢?
首先我们需要对指针解引用操作,把*src
的内容放到*dest
中去,因为一次要拷贝一个字节,我们可以直接强制类型转化成char*
类型就可以访问一个字节了。接着继续往后访问,还需要强制类型转化成char*
类型再+1让指针往后走;该操作需要执行的次数取决于参数num
的取值所以这里用while
循环,随着每一次的操作,num–,直到num为0循环结束。最后该函数设计的时候返回的是一个void*
指针,所以我们可以在循环操作前,先定义一个void* res
用来存放最初始的dest
程序结束,return res;
就可以了。
由上述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从后向前都是可行的,因为没有数据不会在拷贝前被覆盖了
所以我们不能使用memcpy
函数进行在同一个数组里进行内存拷贝!这时候就要用到另一个内存函数memmove
。
此时我们只需思考从后往前拷贝时,应该如何实现
从图中可知,src是
函数原型
memcmp是比较内存区域ptr1和ptr2的前num个字节,比较的是内存大小,*注如果两个字符串相同且num值大于字符串长度的话,不会在\0出停下程序,会继续往后进行比较,直到达到num次数
memcmp
与strcmp
函数功能相似,只不过是可以对所有类型都进行一个字节一个字节的比较,逐字节比较内存的大小。
返回值有三种情况
‘< 0’ :"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 < “参数ptr2”;(VS编译器下返回值为 -1)
‘= 0’: "参数ptr1"与"参数ptr2"内存大小相等;(VS编译器下返回值为 0)
‘> 0’:"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 > “参数ptr2”。(VS编译器下返回值为 1)
函数原型
以字节为单位来设置值
参数分别为:
1 . 一个指向需要被修改的内存空间的地址
2 . 指定修改的内容(int类型)
3 . 需要修改的字节数
memset
函数的作用:在指向的内存空间的前num
个字节内容修改成所指定的int value
的内容,有些类似于memcpy的工作原理。
图示说明
以上就是有关C语言进阶的内容,内存操作函数部分的模拟实现和函数使用说明及方法。
希望该篇文章对大家的学习有所帮助,期待与大家共同进步,持续更新中…
点个关注点个赞吧!