memcpy 和 memmove
都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:
void *memcpy(void *dst, const void *src, size_t count);void *memmove(void *dst, const void *src, size_t count);
他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。
举例说明
int arr[10] = {1,2,3,4,5,6,7,8,9,10}
当src指向1位置,dst指向3位置,当需要复制4个int也就是16个字节时,使用memcpy会造成覆盖问题。
原因:从前向后复制时,1会复制到3位置将还没拷贝的3覆盖为1。因此最后结果为:{1,2,1,2,1,2,7,8,9,10},而我们想要的结果为:{1,2,1,2,3,4,7,8,9,10}
- 出现这种情况的原因就是我们从前向后复制会覆盖还未拷贝的信息,那么修改为从后向前复制即可。但是如果src在dst后面并且存在覆盖,从后向前也会造成覆盖问题。因此我们需要推导条件来选择复制方向。
当存在内存覆盖并且src(源地址)在dst(目标地址)之前,需要使用从后向前的拷贝。
if ((src < dst) && (char*)src + size > (char*)dst) //当然第二个条件可以不需要
具体实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dst, const void* src, size_t size) {
char* psrc; //强转为了char会按照字节拷贝char* pdst;if (dst == nullptr || src == nullptr) {
return nullptr;}//dst在src后面,并且拷贝区间和目标区间存在覆盖(覆盖前面内容),从后向前拷贝if ((src < dst) && (char*)src + size > (char*)dst) {
psrc = (char*)src + size - 1;pdst = (char*)dst + size - 1;while (size--) {
*pdst-- = *psrc--;}}else {
psrc = (char*)src;pdst = (char*)dst;while (size--) {
*pdst++ = *psrc++;}}return dst;
}void* my_emmove(void* dst, const void* src, size_t cnt) {
if (dst == nullptr || src == nullptr) {
return nullptr;}char* dstp = (char*)dst;const char* srcp = (char*)src;if (src < dst) {
dstp += cnt - 1;srcp += cnt - 1;while (cnt--) {
*dstp-- = *srcp--;}}else {
while (cnt--) {
*dstp++ = *srcp++;}}return dstp;
}int main(int argc, char* argv[])
{
char buf[100] = "abcdefghijk";int arr[10] = {
1,2,3,4,5,6,7,8 };int arr1[10] = {
0 };//memcpy(buf+2, buf, 5);my_memcpy(arr + 2, arr, 16);printf("%s\n", buf);
}