0.回顾
strcpy只是做字符串copy,而memcpy和memmove不必关心任何类型数据
1.memcpy()使用:
- strncpy(char* dest, const char* src, size_t count); 两者参数很像
memcpy(void* dest, const void* src, size_t count):把源数据拷贝到dest,大小为count,返回的是目标空间起始地址,即返回无类型的void* - const放在*左边表示指针所指向内容,不能通过指针改变。 const对星和内容一起限定,指针指向内容不能改变,是一种保护。
- 使用示例:
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[5] = { 0 };
memcpy(arr2, arr1, 20);
return 0;
}
效果: 复制的是int类型5个数字,有20个字节,所以如右侧复制了5个
1. 自写memcpy()
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest&&src);
while (count--)
{
assert(dest&&src);
void* ret = dest;
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[5] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}
思路:1.因为memcpy可以复制任何类型的变量,所以必须用void无类型的指针dest和src 2. 写的时候,一个字节一个字节地做 3. 外层循环字节数–,内层先对src强转char*,因为char是一个字节,然后把用星解引用的内容给了强转成char后的dest,最后解引用。然后是两者+1,但是+也得先转为char*,这样才能一个字节一个字节+。 4.最后需要返回dest,即被更改的dest起始,但是经过内层dest已经变了,所以开始的时候先存起来。
2.memmove():重叠内存拷贝
memcpy只适合拷贝两个不同的元素,不可做重叠内层拷贝。 如下图对自己拷贝5个,从位置3起始开,结果得到arr1如右结果,1 2 1 2 1 ,为什么呢? 因为之前的源码写法是从头往后拷贝,而从arr1的第三个开始拷贝,arr1的第一个会覆盖arr1第3个值,随后给6位置拷贝3时,已经丢失了,那么这个时候需要memove()
void* memmove(void* dest, const void *src, size_t count);
memmove做连续地址上的移位。如何复制不会被覆盖,主要是因为重叠,需要考虑从前往后还是从后往前。 如果dest在前而src在后,则从src的头开始往后复制,反之从src的尾->头。 实现
void* my_memmove(void* dest, const void* src, size_t count)
{
assert(dest && src);
char* ret = dest;
if (dest<src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest+1;
src = (char*)src+1;
}
}
else {
while (count--)
{
*((char*) dest+count) = *((char*)src + count);
}
}
return ret;
}
思路 memmove主要是防止同一段变量地址拷贝的覆盖,所以区分src从头到尾复制和src从尾到头,具体解释看上面吧 结果:
|