一.memcpy
声明
1void *memcpy(void *str1, const void *str2, size_t n)
作用
将自str2往后的n个字节的数据,复制到str1往后的n个字节的内存当中
模拟实现
1
2
3
4
5
6
7
8
9void* 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发生重叠时,无法需拷贝的数据可能被覆盖掉,导致无法达到所需的效果
举一个例子来解释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20void* 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
声明
1void *memcpy(void *str1, const void *str2, size_t n)
作用
将自str2往后的n个字节的数据,复制到str1往后的n个字节的内存当中
模拟实现
1
2
3
4
5
6
7
8
9void* 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发生重叠时,无法需拷贝的数据可能被覆盖掉,导致无法达到所需的效果
举一个例子来解释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20void* 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时,后拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void* 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内容请搜索靠谱客的其他文章。
发表评论 取消回复