引言

本文介绍memcpy的使用和模拟实现、memmove的使用和模拟实现、memcmp使用、memset使用

猪巴戒:个人主页✨

所属专栏:《C语言进阶》

跟着猪巴戒,一起学习C语言

目录

引言

memcpy

memcpy的使用

memcpy的模拟实现

memmove

memcpy函数不用来处理重叠的内存的数据拷贝:

memmove的模拟实现

总结:

模拟实现代码

memcmp

memset


memcpy

void * memcpy ( void * destination, const void * source, size_t num )
  • memcpy的作用就是将source的内容拷贝到destination
  • num说明了拷贝多少个字节
  • 返回值是destination.

memcpy的使用

#include#includeint 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#includevoid* 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#includevoid* 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#includevoid* 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#includeint main(){char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);return 0;}