### 这里主要介绍memcpy 和 memmove 的原理和模拟以及 memcmp 、memset的基本用法。
它们的头文件都是string.h
C语言内存函数操作的是内存,也就是通过地址去操作,所以此类函数操作的对象相当广泛,了解学习有关的基本知识会对我们很有帮助。
## memcpy
对于内存函数我们可以通过联想到一些字符串函数来理解学习,不同的是内存函数操作的是地址,所以不限制形参的类型,而字符串函数只能对字符串进行相关操作;
解释:这个函数返回类型是void* ,前两个参数也是void* ,原因:void* 可以接收任何类型的指针;第一个参数是“目的地”,第二个参数是“来源”,含义是从source里面copy的内容将放到destination里面去,最后一个参数指明了操作的字节个数(注意:无论指针指向的元素是什么类型的,这个函数都是一个字节一个字节去操作草拷贝的)
示例
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);//将arr2里面的5个整型数据拷贝到arr1里面。
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
值得说明的是:当你操作的两个数组里面的元素有内存重叠(地址一样)的时候,使用这个函数最终得到的结果是未定义的,为了避免,我们使用另一种内存函数,下面来介绍。
## memmove
这个函数和memcpy几乎无异,唯一不同的是这个函数可以操作内存重叠的元素
示例
#include<stdio.h>
#include<string.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr, arr + 2, 20);//我们将3,4,5,6,7往1,2,3,4,5的位置copy的时候有内存重叠
int i = 0;
for (; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
### memcpy和memmove的模拟实现
memcpy模拟
void* my_memcpy(void* arr1, const void* arr2, size_t num)
{
assert(arr1 && arr2);
void* ret = arr1;
int i = 0;
for (i = 0; i <num; i++)
{
*((char*)arr1) ++ = *((char*)arr2) ++;//一个字节一个字节copy,++后置,每次换完再完后跳一个字节
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5 };
my_memcpy(arr1, arr2, 20);
int len = sizeof arr1 / sizeof arr1[0];
for (int i = 0; i <len; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
memmove
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest <= src)
{
while (num--)
{
*((char*)dest)++ = *((char*)src)++;
}
}
else if (dest > src)
{
while(num--)
{
*(((char*)dest) + num) = *(((char*)src) + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+3,arr1 ,20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
解释my_memmove里面的选择语句:我们已经知道,memmove无视内存的重叠,我们要想出一种办法保证copy的时候内存不会重叠;如果dest地址比src大,那么src指向的数组就要从后往前copy,看到上面代码,此时dest>src,如果从前往后(也就是依次把1、2、3、4、5copy到4、5、6、7、8)我们会发现当1、2、3copy完的时候,原本4、5、6变成了1、2、3,这一部分正确,但是本是要被copy的4、5变成了1、2,这时候就7、8的位置就变成了1、2而非4、5,最后得到的结果是:1,2,3,1,2,3,1,2,9,10;而不是1,2,3,1,2,3,4,5,9,10;所以我们要从后往前,也就是把5,4,3,2,1依次copy到8、7、6、5、4的位置;
如果dest<src,那么反之同理。
### memcmp和memset
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "hello world";
memset (str,'x',6);
printf(str);
return 0;
}
memcmp参照strcmp理解
#include <stdio.h>
#include <string.h>
int main()
{
int str1[] = { 1,2,3,4,5 };
int str2[] = { 1,2,3,5,6 };
int ret = memcmp(str1, str2, sizeof(str1));//比较整个
printf("%d\n", ret);
}
————完