1.memcpy
strcpy只能拷贝字符串,而memcpy不仅于此,还可以拷贝其他类型的内容。
例子
int main()
{
int arr1[10] = { 0 };
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr1, arr2, sizeof(int)*5);//可以了解为从arr2开始,拷贝20个字节到arr1指向的空间
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", *(arr1 + i));
}
return 0;
}
结果
1 2 3 4 5
注意
(1)目标数组和源数组都得保证足够大。
(2)这个函数若还没拷贝完num个字节,遇到’\0’并不会停下来。
(3)如果要从源数组的其他位置开始拷贝,可以修改起始地址,例如memcpy(arr1,arr2+4,sizeof(int)*5)。
2.模拟实现memcpy
void* my_memcpy(void* dest, const void* sour, int num)
{
assert(dest && sour);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)sour;
dest = (char*)dest + 1;
sour = (char*)sour + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1, arr2, sizeof(int)*5);//可以了解为从arr2开始,拷贝20个字节到arr1指向的空间
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", *(arr1 + i));
}
return 0;
}
结果
1 2 3 4 5
疑惑
(1)如果自己给自己拷贝会是怎样的结果?(即dest和sour有重叠部分)例如memcpy(arr1+2,arr1,20)
其可能出现以下两种结果:
1 2 1 2 3 4 5 8 9 10
1 2 1 2 1 2 1 8 9 10
(2)为什么会出现第二种结果?当你按图中的步骤做时
(3)这样的结果是达不到我们的预期的,如何才能得出第一种结果?
在同数组中,当sour在dest的左边时,将sour指向的字节按从前往后的方式拷贝到dest指向的位置,肯定会发生覆盖,从而导致重复。那我们就对源数据从后向前处理;当sour在dest的右边时,我们对源数据从前向后处理。
(4)以上涉及memmove的模拟实现,我们先了解下memmove
3.memmove
memmove相当于加强版的momcpy,也是拷贝内存块,但它能实现内存块的重叠拷贝。
例子
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(arr1 + i));
}
return 0;
}
结果
1 2 1 2 3 4 5 8 9 10
4.模拟实现memmove
void* my_memmove(void* dest, void* sour, int num)
{
assert(dest && sour);
void* ret = dest;
if (sour > dest)
{
while (num--)
{
*(char*)dest = *(char*)sour;
sour = (char*)sour + 1;
dest = (char*)dest + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)sour + num);
}
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(arr1 + i));
}
return 0;
}
结果
1 2 1 2 3 4 5 8 9 10
注意
要拷贝的数组要有足够的空间存放被拷贝的内容,防止越界访问
5.memcmp
这个函数的返回值和strcpy的返回值相同,如果当ptr1指向的字节等于ptr2指向的字节,那么两者++,若早已比较num个字节,则返回0;如果当ptr1指向的字节大于ptr2指向的字节,就返回大于0的数字;如果当ptr1指向的字节小于ptr2指向的字节,则返回小于0的数字。
例子
int main()
{
int arr1[] = { 1,2,3 };
int arr2[] = { 1,2,5 };
printf("%d", memcmp(arr1, arr2,9));//比较9个字节
//已只数据在内存中的存储方式是小端存储(低位字节序放在低地址处,高位字节序放在高地址处)
//arr1在内存中的存储:01 00 00 00 02 00 00 00 03 00 00 00
//arr2在内存中的存储:01 00 00 00 02 00 00 00 05 00 00 00
//比较前9个字节,到第九个字节时05>03,所以arr1<arr2,返回小于0的数字
return 0;
}
结果
-1
6.memset
例子
int main()
{
char arr[] = "hello world";
//将hello改为xxxxx
memset(arr, 'x', 5);
printf("%s\n", arr);
//将world改为yyyyy
memset(arr + 6, 'y', 5);
printf("%s\n", arr);
return 0;
}
结果
xxxxx world
xxxxx yyyyy
注意
(1)memset是以字节为单位处理的
(2)memset通常用来初始化数据