引言
本文介绍memcpy的使用和模拟实现、memmove的使用和模拟实现、memcmp使用、memset使用
✨ 猪巴戒:个人主页✨
所属专栏:《C语言进阶》
🎈跟着猪巴戒,一起学习C语言🎈
目录
memcpy
void * memcpy ( void * destination, const void * source, size_t num )
- memcpy的作用就是将source的内容拷贝到destination
- num说明了拷贝多少个字节
- 返回值是destination.
memcpy的使用
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
memcpy的模拟实现
内存函数就是无论是什么类型的数据都可以使用。
void* ,属于通用类型的指针,可以存放任意类型的地址。
assert,断言,保证dest和source不是空指针。
num是需要拷贝的字节数。
通过将地址转化为(char*)的形式,将需要拷贝的内容一个字节一个字节地将它们拷贝,就可以实现各种数据的拷贝。
然后dest转移到下一个字节,source转移到下一个字节,知道拷贝完num个字节算结束。
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{
assert(dest && source);
void* start = dest;
while (num--)
{
*(char*)dest = *(char*) source;
dest = (char*)dest + 1;
source = (char*)source + 1;
}
return start;
}
memmove
void * memmove ( void * destination, const void * source, size_t num )
- 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
- 参数和memcpy是一样的。
memcpy函数不用来处理重叠的内存的数据拷贝:
将arr1数组改成{1,2,1,2,3,4,5,8,9,10},从第三位元素开始,拷贝自己的第一到第五个元素
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{
assert(dest && source);
void* start = dest;
while (num--)
{
*(char*)dest = *(char*) source;
dest = (char*)dest + 1;
source = (char*)source + 1;
}
return start;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
memcpy在重叠内存拷贝的时候,第三个元素被改成1,第四个元素被改成2,
而第五个元素本来是应该赋值为3的,但是第三个元素已经被改成1了。
第六个元素本来是由第四个元素重新赋值,但是第四个元素被改成了2.
memmove的模拟实现
如果说我们要将红色部分拷贝到蓝色部分
从前向后拷贝不行,我们要将红色的部分拷贝到蓝色的部分,先将第一个元素拷贝到第三个元素,红色区域的内存被改变,等到将第三个元素拷贝到第五个元素的时候,第三个元素已经发生改变。
从后向前拷贝,如果我们可以先将第五个元素拷贝到第七个元素,这样红色的三、四、五元素先拷贝完后被改变就可以把数值3,4,5成功传到第五、六、七个元素。
这一次,
从后向前拷贝不行,我们要将红色部分拷贝到蓝色的部分,先将第七个元素拷贝到第五个元素,首先改变了第五个元素的内容,到时候第五个元素还要对第三个元素进行拷贝。
从前向后拷贝,如果我们先将第三个元素拷贝到第一个元素,等轮到第三个元素进行拷贝的时候,第三个元素里的内容已经转出去了,转到第一个元素了,那么第三个元素的内容就可以随便修改了。
总结:
为了保证source中的数据在拷贝之前就被修改,
- 当dest在source的右边的时候,采用从后向前的方式
- 当dest在source的左边的时候,采用从前向后的方式
模拟实现代码
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* source, size_t num)
{
assert(dest && source);
void* start = dest;
if (dest < source)
{
//从前向后
while (num--)
{
*(char*)dest = *(char*)source;
dest = (char*)dest + 1;
source = (char*)source + 1;
}
}
else
{
//从后向前拷贝
while (num--)
{
*((char*)dest + num) = *((char*)source + num);
}
}
return start;
}
memcmp
可以比较任意类型的数据
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
- ptr1指向的第一个空间
- ptr2指向的第二块空间
- ptr1和ptr2之间的内存比较
- num表示需要比较的字节大小
arr1和arr2比较,arr1比arr2小,返回小于0的数值。
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,3,2 };
int ret = memcmp(arr1, arr2, 12);
printf("%d", ret);
return 0;
}
memset
void * memset ( void * ptr, int value, size_t num )
- ptr需要填充的地址空间
- value,填充什么字符
- num,填充几个字节
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "hello world";
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}