数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。注意是以字节为单位进行拷贝。函数声明如下:
第二个参数 src:源地址,即你要从哪开始拷贝。
第三个参数 count:字节数,即从源地址起始位置开始一共要拷贝多少个字节。
第一个参数 dst:目的地址。也就是你拷贝的内容要放到哪。
返回值:返回目标空间的地址。
该函数有如下两个注意事项:
因为是逐字节拷贝,所以解引用的时候,每次访问只能访问一个字节,前面在说指针类型的时候提到,指针类型决定了解引用每次可以访问多少个字节。
因此,在拷贝之前,先将源地址和目标地址的指针类型转化为 char* 类型,这样的话,每次解引用就只会访问一个字节。
#include
#include void* my_memcpy(void* dst, const void* src, size_t num)
{assert(dst && src);char* target = (char*)dst; // 转化为 char*,解引用时只会访问一个字节 const char* source = (const char*)src; while (num--){*target = *source;target++;source++;}return dst;
}int main() {int dst[10] = { 0 };int src[5] = { 1,2,3,4,5 };my_memcpy(dst, src, sizeof(src));for (size_t i = 0; i < 10; i++){printf("%d ", dst[i]);}return 0;
}
测试结果如下:
当源地址和目标地址没有重叠的时候,memmove函数 和 memcpy函数的功能是一样的,但是如果遇到内存重叠的情况,比如将源地址的第1 ~ 4个字节拷贝到源地址的第3 ~ 6的字节位置上。
函数声明如下, 参数解析可以参考 memcpy 函数
在模拟实现的时候,需要考虑的是,源地址和目的地址的位置。如果源地址在目的地址的左边,此时应该先将末尾的字节拷贝到目标地址的末尾。如果按正常顺序拷贝的话,就会变成右边这种情况,明明 3 也是要拷贝到目标地址的,但是现在却被新拷贝的覆盖了。
如果 边,应该是从后往前拷贝。这个时候相当于是把蓝色框里的内容向后移动了一样,最先移动的是最右边的内容。
如果源地址在目的地址的右边,那么这个时候,就应该是从前往后拷贝。这个时候就相当于是把蓝色框里的内容向前移动了一样,最先移动的是最左边的内容。
void* my_memmove(void* dst, const void* src, size_t num)
{assert(dst && src);char* target = (char*)dst;const char* source = (const char*)src;if (src < dst){// 源地址在目的地址的左边while (num--){*(target + num) = *(source + num);}}else if (src > dst){// 源地址在目的地址的右边while (num--){*target = *source;target++;source++;}}else{// 无需拷贝,直接返回return (void*)src;}
}int main() {int arr[8] = { 1,2,3,4,5,6,7,8 };my_memmove(arr, arr + 2 , 4 * sizeof(int)); //移动4个元素(16个字节)for (size_t i = 0; i < 8; i++){printf("%d ", arr[i]);}return 0;
}
测试结果为: