概述
一.memcpy
声明
void *memcpy(void *str1, const void *str2, size_t n)
作用
将自str2往后的n个字节的数据,复制到str1往后的n个字节的内存当中
模拟实现
void* my_memcpy(void* str1, const void* str2, int n)
{
while (n--)
{
*(char*)str1 = *(char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
}
注意
在使用过程中,str1与str2中的n个字节不能重叠。这也是memcpy很大的一个缺陷,而memmove可以很好的解决整个问题
二.memmove
在使用memcpy时,当str1与str2发生重叠时,无法需拷贝的数据可能被覆盖掉,导致无法达到所需的效果
举一个例子来解释
void* my_memmove(void* str1, const void* str2, size_t n)
{
void* ret = str1;
while (n--)
{
*(char*)str1 = *(char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
return ret;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
my_memmove(arr+2, arr, 20);
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
return 0;
}
想要达到的效果是,将arr1为起始的20个字节的数据,存放到arr1+2后的20个字节的内存中。
原数组 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
目的数组 | 1 | 2 | 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 |
实际数组 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 8 | 9 | 10 |
这为什么呢?
一.memcpy
声明
void *memcpy(void *str1, const void *str2, size_t n)
作用
将自str2往后的n个字节的数据,复制到str1往后的n个字节的内存当中
模拟实现
void* my_memcpy(void* str1, const void* str2, int n)
{
while (n--)
{
*(char*)str1 = *(char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
}
注意
在使用过程中,str1与str2中的n个字节不能重叠。这也是memcpy很大的一个缺陷,而memmove可以很好的解决整个问题
二.memmove
在使用memcpy时,当str1与str2发生重叠时,无法需拷贝的数据可能被覆盖掉,导致无法达到所需的效果
举一个例子来解释
void* my_memmove(void* str1, const void* str2, size_t n)
{
void* ret = str1;
while (n--)
{
*(char*)str1 = *(char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
return ret;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
my_memmove(arr+2, arr, 20);
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
return 0;
}
想要达到的效果是,将arr1为起始的20个字节的数据,存放到arr1+2后的20个字节的内存中。
原数组 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
目的数组 | 1 | 2 | 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 |
实际数组 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 8 | 9 | 10 |
这为什么呢?
正在上传…重新上传取消
重叠部分的数据,在拷贝过程中已经被覆盖了,数据已经丢失了
从这里不难发现,memcpy无法处理出现重叠的情况
在这时,我们可以使用memmove
memmove的参数,返回值等等与memcpy均相同,不过他可以处理重叠的情况
正在上传…重新上传取消
正在上传…重新上传取消 对比上下两个例子,不难发现重叠部分是分情况的,
一是与原数据前部分与目标地址重合,另一种是后部分与目标地址重合
想要处理重叠部分,重点便是先使用重叠部分的数据,防止重叠部分的数据被覆盖后,导致的数据丢失
可以通过str1 与 str2 的的地址位置关系来判断
目前的讨论是以重叠为前提的,不重叠时以下要讨论的两种方法都能实现
为了方便讨论,将memcpy中的拷贝方法称作为前拷贝,反之先拷贝高地址处数据的称之为后拷贝
先讨论一个特殊情况
str1 == str2
无论是前拷贝还是后拷贝,均无影响。
都是将数据本身赋值给本身
str1 > str2
重叠部分的数据位于源数据的后部分,应优先使用重叠部分
即应使用后拷贝
str1 < str2
重叠部分的数据位于源数据的前部分,应优先使用重叠部分
即应使用后拷贝
总体而言
当str1 < str2时,前拷贝
当str >= str2时,后拷贝
void* my_memmove(void* str1, const void* str2, size_t n)
{
void* ret = str1;
if (str1 < str2)
{
while (n--)
{
*(char*)str1 = *(char*)str2;
str1 = (char*)str1 + 1;
str2 = (char*)str2 + 1;
}
}
else
while(n--)
*((char*)str1+n) = *((char*)str2+n);
return ret;
}
最后
以上就是舒心冰棍为你收集整理的memcpy、memmove的模拟实现一.memcpy二.memmove一.memcpy二.memmove的全部内容,希望文章能够帮你解决memcpy、memmove的模拟实现一.memcpy二.memmove一.memcpy二.memmove所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复