谢谢观看!希望以下内容帮助到了你,对你起到作用的话,可以一键三连加关注!你们的支持是我更新地动力。
因作者水平有限,有错误还请指出,多多包涵,谢谢!
一、memcpy
使用和模拟实现(内存拷贝)
memcpy
函数的形参部分:
void * memcpy ( void * destination, const void * source, size_t num );
//destination表示目标空间的地址
//source表示源空间的地址
//num表示要从源空间中拷贝到目标空间的字节个数
//void* 表示可以接收各种类型的地址,比较当我使用这个函数是,设计函数的人又不知道我会传递什么样的数据类型,所以有无具体类型指针接收
//返回类型是void *,表示返回的是目标空间的起始地址
memcpy
函数的注意事项:
- 函数
memcpy
从source
的位置开始向后复制num
个字节的数据到destination
指向的内存位置。 - 这个函数在遇到
'\0'
的时候并不会停下来。 - 如果
source
和destination
有任何的重叠,复制的结果都是未定义的。(比如将数组1,2,3,4,5,6,7,8,9,10
的1,2,3,4,5
拷贝到3,4,5,6,7
,因为内存有重叠,会导致结果是未定义,所以memcpy
函数不负责重叠内存的拷贝,只负责不重叠的内存,非要使用,结果是未定义,而处理重叠内存是用memmove
函数的)
memcpy
函数的基本用法:
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
//将arr1中的3,4,5,6,7拷贝放到arr2中
memcpy(arr2, arr1 + 2, 20);
return 0;
}
memcpy
函数的模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* dest_start = dest;
int i = 0;
assert(dest && src);
for (i = 0; i < num; i++)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return dest_start;//返回起始位置地址
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
//将arr1中的3,4,5,6,7拷贝放到arr2中
my_memcpy(arr2, arr1 + 2, 20);
return 0;
}
二、memmove
使用和模拟实现
memmove
函数的形参部分:
//参数和memcpy一模一样
void * memmove ( void * destination, const void * source, size_t num );
//destination表示目标空间的地址
//source表示源空间的地址
//num表示要从源空间中拷贝到目标空间的字节个数
//void* 表示可以接收各种类型的地址,比较当我使用这个函数是,设计函数的人又不知道我会传递什么样的数据类型,所以有无具体类型指针接收
//返回类型是void *,表示返回的是目标空间的起始地址
memmove
函数的注意事项:
- 和
memcpy
的差别就是memmove
函数处理的源内存块和目标内存块是可以重叠的。 - 如果源空间和目标空间出现重叠,就得使用
memmove
函数处理。
memmove
函数的基本用法:
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1 , 20);//结果为1,2,1,2,3,4,5,8,9,10
return 0;
}
memmove
函数的模拟实现:
实现思路:memmove
函数的模拟实现是需要分情况来讨论的,对于重叠部分,当dest
和src
的地址前后不一样时,采用拷贝的方式也不一样,可能从前面拷贝到后面,也可能从后面拷贝到前面。
void* my_memmove(void* dest, const void* src, size_t num)
{
void* dest_start = dest;
assert(dest && src);
if(dest < src)//前--->后
{
while(num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//后--->前
{
while(num--)
{
*((char*)dest+num) = *((char*)src+num);
}
}
return dest_start;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1 , 20);
int i = 0;
for(i=0;i<10;i++)
{
printf("%d ",arr1[i]);
}
return 0;
}
补充:
C语言标准规定memcpy
函数只要能实现不重叠的拷贝就行,重叠的拷贝交给memmove
函数,我们发现vs上的库函数中的memcpy
函数也能实现重叠内存的拷贝,觉得麻烦的以后都可以使用memmove
函数,它不管重叠还是不重叠都可以就行拷贝。
三、memset
函数的使用
memset
函数的形参部分:memset函数是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
void * memset ( void * ptr, int value, size_t num );
//ptr表示指向了要被填充的内存的地址
//value表示每一个字节要填充的值是什么
//num表示要设置的字节个数是多少
memset
函数的基本用法:
int main()
{
char arr[] = "hello world";
memset(arr+6, 'x' , 5);
printf("%s\n",arr);//结果为:hello xxxxx
return 0;
}
memset
函数的注意事项:
memset
函数是把每一个字节设置为你想要的值
int main()
{
int arr[10] = {0};
memset(arr,1,4);//此时的意思是,将每一个字节都设置为1,共设置4个字节,从arr数组的首元素地址开始设置
//并不是将arr第一个元素0设置为1,而是0x01010101=16843009
return 0;
}
四、memcmp
函数的使用
memcmp
函数的形参部分:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
- 比较从
ptr1
和ptr2
指针指向的位置开始,向后的num
个字节 ptr1
>ptr2
,返回大于0的数ptr1
=ptr2
,返回等于0的数ptr1
<ptr2
,返回小于0的数
memcmp
函数的基本用法:
int main()
{
char arr1[] = {1,2,3,4,5};
char arr2[] = {1,2,3,6,5};
int ret = memcmp(arr1,arr2,12);
printf("%d ",ret);//0
int ret = memcmp(arr1,arr2,13);
printf("%d ",ret);//-1
return 0;
}