本文介绍了内存处理函数memcpy、memmove、memcmp和memset的原理与实现。重点分析了memcpy和memmove的区别:memcpy不能处理内存重叠情况,而memmove通过判断目标地址位置选择从前向后或从后向前拷贝,支持自拷贝。文章提供了这两个函数的模拟实现代码,其中memmove通过比较目标地址和源地址来确定拷贝方向。还简要说明了memcmp用于内存数据比较
目录
1.memcpy函数

字符串拷贝strcpy和strncpy是有一定局限性的,只能拷贝字符串,而memcpy可以拷贝任意类型的数据,单位是字节。

1.1 模拟实现
#include
#include
// 返回目标空间的的首地址
void* my_memcpy(void* des,void* src,size_t num)
{
assert(des && src);
void* ret = des;
while (num--)
{
*((char*)des) = *((char*)src);
((char*)des)++;
((char*)src)++;
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, sizeof(arr1));
return 0;
}
2.memmove函数
我们发现:自己实现的memcpy不能实现自己拷贝自己,这是因为在逐字节拷贝的时候,后面的元素再去拷贝前面的字节,前面的字节已经被改过了;但是库函数是可以自己拷贝自己的。
memmove能够实现自己拷贝自己

2.1 模拟实现
情况1:dest < src,此时应该从前向后拷贝,这样就会避免,拷贝修改之后的值。

情况2:当des > src,此时从后往前拷贝。

总体区域划分:

方案①:1、3区域从前往后拷贝;2区域从后往前拷贝;
方案②:1区域从前向后(dest > src);23区域从后往前拷贝(dest < src);
这里采用方案②,只需要判断dest 和 src的大小即可。
#include
#include
#include
void* my_memmove(void* dest, void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest 倒数第二个
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7 ,8,9,10 };
int arr2[20] = { 0 };
//my_memcpy(arr2, arr1, sizeof(arr1));
my_memmove(arr1, arr1 + 3, 12);
int i = 0;
for(i = 0;i < 10;i++)
{
printf("%d\n", arr1[i]);
}
return 0;
}

3.memcmp函数


第一个数组的内存中的数据比第二个内存中的数据要大。
4.memset函数

使用来初始化内存的,第一个参数是起始地址,第二个参数是初始化的值,第三个是初始化的字节个数。

需要注意的是,这里的初始化是按照字节初始化的,所以尽量给一个字节类型的数据。


浙公网安备 33010602011771号