C语言函数:内存函数memmove()以及实现与使用。
memmove():
头文件:#include <string.h>
函数参数:
可以发现memmove()函数的形参与memcpy()函数是一样的:
C语言函数:内存函数memcpy()以及实现_srhqwe的博客-CSDN博客
不仅形参一样,形参的意思几乎也是一样的。
作用:
从source开始到后num个字节,拷贝到destination到后num个字节。
内存重叠:
memcpy()函数如果遇到内存重叠,就无法得到理想的拷贝。
而memmove()函数就恰恰解决了这一问题,可以看到memcpy留下的内存重叠问题:
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memmove(arr1+2, arr1,5*sizeof(int));
return 0;
}
memmove解决了这一问题。
memmove()函数的模拟实现:
memmove函数实现的重点在于:是如何解决内存重叠问题的。
只有解决内存重叠问题,其余的代码其实与memcpy是相近的。
内存重叠问题的解决:
可以看到上图,我们将12345拷贝到34567,遇到内存重叠问题是因为,1拷贝到3,2拷贝到4,当要将3拷贝到4时,发现3以及变成了1。因此后面无法继续。
既然src从首项1开始拿数据显然不行,那试着从末项5开始拿数据:5拷贝到7,4拷贝到6,3拷贝到5,2拷贝到4,1拷贝到3。似乎从后往前是可以的。
似乎从后往前拷贝就可以了。
再看:
与上面作比较,src与dest交换了位置。
此时再src从后往前是:7拷贝到5,6拷贝到4,当5要拷贝到3时,发现这里的5已经变成了7。因此又遇到了内存重叠的问题。
那再试试从前往后:3拷贝到1,4拷贝到2,5拷贝到3,6拷贝到4,7拷贝到5.
!此时发现,从前往后解决了内存重叠问题。
一会从前往后,一会从后往前。到底怎样才是正确的呢?
细心的会发现。当src处于dest左边的时候需要从后往前,当src处于dest右边的时候需要从前往后
但一切的前提是,它们有内存重叠。如果没内存重叠,那么也不会遇到问题。此时无论从前往后还是从后往前都可以。
我们知道,在数组内,地址的大小是由低到高变化的。下标越大地址越大。 因此:
当dest<src时,说明dest在src左边。
当dest>src时,说明dest在src右边。
当dest=src时,说明dest与stc彻底重合了,
无论dest>src还是<src,如果相差很多,导致没有内存重合。无论从前往后还是从后往前都可以。dest=src彻底重合更没得说了。都彻底重合了。那么动都不用动了。
代码实现:
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
void* my_memmove(void* dest, const void* sour, size_t num)
{
if (dest < sour)
{
for (int i = 0; i <= num; i++)
{
*((char*)dest + i) = *((char*)sour + i);
}
return dest;
}
else if (dest > sour)
{
for (int i = num; i >=0; i--)
{
*((char*)dest + i) = *((char*)sour + i);
}
return dest;
}
else
{
return dest;
}
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memmove(arr1+2, arr1,5*sizeof(int));
return 0;
}
代码和memcpy很像,不同的就是多了条件判断,以及从后往前拷贝。