strcpy、strcat、strcmp都是字符串拷贝函数。
对于其它类型的拷贝,需要memcpy函数。
memcpy
完成内存数据拷贝。
memcpy函数的返回类型是void*,有三个参数,两个字符指针,一个整型。
返回值是目标地址的起始地址。
第一个参数是目标的起始地址,第二个参数需要拷贝的数据的起始地址,第三个参数是需要拷贝多少个字节。
memcpy的功能是将src地址处的count个字节数据从dest地址处开始拷贝。如果目标地址和源地址是同一块空间,可能会覆盖数据导致拷贝失败。
#include <stdio.h>
#include <assert.h>
// 模拟实现memcpy
void* Memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
while (count--)
{
// 先强制类型转换,再解引用
*(char*)dest = *(char*)src;
// void*指针无法加减,先要强制类型转换
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[5] = { 1,2,3,4,5 };
Memcpy(arr1, arr2, 4 * 5);
for (int i = 0; i < 10; ++i)
{
printf("%d ", arr1[i]);
}
return 0;
}
实现memcpy的作者,不知道使用者传的地址是什么类型的,要使用void*类型作为形参,能够接收所有类型的指针。
地址都是void*类型的,需要强制类型转换才能进行运算和解引用。
对于同内存拷贝,memcpy还是会有问题,memmove就是专门实现同内存拷贝的。
memmove
完成内存数据的拷贝,同时可以完成同内存拷贝。
memmove函数的返回类型是void*,有三个参数,两个字符指针,一个整型。
返回值是目标地址的起始地址。
第一个参数是目标的起始地址,第二个参数需要拷贝的数据的起始地址,第三个参数是需要拷贝多少个字节。
memcpy的功能是将src地址处的count个字节数据从dest地址处开始拷贝。如果目标地址和源地址是同一块空间,可能会覆盖数据导致拷贝失败。
#include <stdio.h>
#include <assert.h>
void* Memmove(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
// 同内存拷贝,目标地址比源地址小,从前往后拷贝不会出现数据覆盖。
if (dest < src)
{
while (count)
{
// 先强制类型转换,再解引用
*(char*)dest = *(char*)src;
// void*指针无法加减,先要强制类型转换
dest = (char*)dest + 1;
src = (char*)src + 1;
--count;
}
}
// 同内存拷贝,目标地址大于源地址,从前往后拷贝会覆盖数据,使用从后往前拷贝
else
{
// 地址加count,找到的是最后一个数据的下一个地址,需要count先减1
while (count--)
{
// 先强制类型转换,再解引用
*((char*)dest+count) = *((char*)src+count);
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5 };
Memmove(arr + 2, arr, 4 * 5);
for (int i = 0; i < 10; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}