目录
一、memcpy使用和模拟实现
二、memmove使用和模拟实现
三、memset函数的使用
四、memcmp函数的使用
正文开始
一、memcpy使用和模拟实现
memcpy内存拷贝函数,从源头位置source拷贝num个字节数据到目标空间destination处,返回的是数组首元素地址(拷贝单位字节不是元素!!!)
由于不知道使用者要拷贝的数据类型,所以用void*指针接收,拷贝时是一个字节一个字节拷贝,而不是一个元素一个元素,需包含头文件string.h
此函数是内存拷贝函数,只针对内存拷贝,遇到‘\0’不会停下来;若函数自己拷贝自己,源头和目标空间有重叠,数据拷贝时将会被覆盖
1.1 memcpy使用
arr1 数组是整型数组,一个整型等于4个字节,拷贝20个字节把前五个元素拷到arr2(4*5=20)
拷贝的空间必须开辟足够大,能存放的下你要拷贝内容
1.2 memcpy模拟实现
要想完全学会一个函数,就得试着自己模拟实现出来
以下是 my_memcpy完整的代码实现,红框框起来的部分可能有些读者会有疑惑,接下来将一 一攻克(再次声明按字节进行拷贝,20个字节等于5个整型)
首先, my_memcpy函数对源头数据进行内存拷贝时并不会改变原数据,加上const修饰;其次对传过来的地址用assert断言是否为空指针,以上都是增加代码的强健性。
再者,在不知道数据类型的情况下进到循环内部,将其强制类型转换为char*,不管什么数据都一个字节一个字节拷贝;但是强制类型转换是一次性的,不可能一次类型转换下条代码还能使用,所以当一个字节拷贝完毕需要指针向后移动时,再进行强制类型转换+1向后移动一个字节
最后,my_memcpy函数返回目标数组的首元素地址,dest在循环中向后移动时已改变起始位置,所以一开始要定义个变量先存放首元素地址以便返回
返回的首元素地址依然是void* 类型,若后续要进行元素打印必须得再强制类型转换为int*类型
二、memmove使用和模拟实现
上面提到:若函数自己拷贝自己,源头和目的地的空间数据有重叠,拷贝时数据会被覆盖
以下出现数据覆盖并未达到我们预期,所以若函数自己拷贝自己用memmove
2.1 memmove使用
memmove的参数和返回值与 memcpy的一模一样,差别在于memmove函数处理的源内存块和目标内存块是可以重叠的。
2.2 memmove的模拟实现
解析:假设红框是目标空间dest,蓝框是源头数据sour
情况1
数组随着下标的变化,地址从低到高变化。整型数组arr1中,若源数据sour在目标空间dest左侧,要将源头数据拷贝到目标空间中,若从前向后拷贝:3改为1, 4改为2,而到3时源数据已经被改为1,若继续拷贝将重复上面代码1 2 1 2 1 达不到需要效果,所以此情况不能从前向后拷贝数据,该如何拷贝呢?
可以选择从源数据的末尾开始拷贝,把5给7, 4给6, 3给5,依次下去可实现完整拷贝
情况2
若源数据sour在目标空间dest右侧,延续情况1的做法从后向前拷贝的话又会出现数据覆盖,所以改成从源头数据的开头开始依次拷贝
综上所述:memmove函数在进行拷贝时要分两种情况讨论,以目标空间dest为分界线若
情况1:sour<dest 从后向前拷贝
情况2:sour>dest 从前向后拷贝
情况3:sour=dest 从前向后拷,从后向前拷贝都可以,为了方便区分我选择拷贝与 情况2 一致
代码:
进入到my_memove函数,先if语句判断它是两种情况中的哪一种,若是从后向前拷贝得先找到源数据的最后一个字节位置和目标空间的最后一个字节位置,要如何找到呢?
加上num个字节找到最后一个字节,随着num--从而实现从后向前拷贝
三、memset函数的使用
memset函数是用来设置内存的,将内存中的值以字节为单位设置成想要的内容
一般情况下用于将整个数组设置为0
如以下代码,将arr1数组中的前6个字节设置‘x’
四、memcmp函数的使用
memcmp函数从ptr1和ptr2指针指向的位置开始,对应字节比较num个字节大小与字符串的长度无关
返回值如下:
memcmp函数对应比较arr1和arr2内的3个字节
完