前言
大家好呀,我是Humble
在上一讲中我们介绍了字符函数和字符串函数(还没看过的小伙伴可以传送到文章底部我创建的专栏中进行阅读哦)
当然,在我们的库函数中,除了那种函数之外,还有很多其他的函数 ,比如我们今天要介绍的一组函数,即内存相关的函数
好了,废话不多说,开始我们今天的学习吧!
一.memcpy使用和模拟实现
memcpy()函数的功能是内存拷贝(将source的数据拷贝到destination中去,拷贝的数量是num个)
需要引用的头文件:
#include <string.h>
下面直接看一个例子:
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = {0};
//将arr1中的1 2 3 4 5,拷贝到arr2中
memcpy(arr2, arr1, 5*sizeof(int));
int i = 0;//打印arr2
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
那么打印结果为:
这是整形数组的拷贝
下面我们来使用这个函数来拷贝字符数组,加深对它的理解
int main()
{
char arr1[20] = "hello world";
char arr2[20] = { 0 };
memcpy(arr2, arr1, 5);
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%c ", arr2[i]);
}
return 0;
}
好,现在我们应该对这个函数有了一个初步的理解,我们来看一下下面2点结论:
1.这个函数在遇到 '\0' 的时候并不会停下来,它是以num的值来进行拷贝的
2.如果source和destination有任何的重叠,拷贝的结果都是未定义的,即这个函数不负责重 叠的拷贝
下面我们来模拟实现一下这个函数
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//将arr1中的4 5 6 7 8,拷贝到arr2中
my_memcpy(arr2, arr1+3, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
好,我们回过头来再来看一下上面结论的第二点
如果source和destination有任何的重叠,拷贝的结果都是未定义的,即这个函数不负责重 叠的拷贝
比如说下面这个代码,
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1+2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]); //希望得到 1 2 1 2 3 4 5 8 9 10
}return 0;
}
我希望得到 1 2 1 2 3 4 5 8 9 10
让我们打印一下
实际结果是:1 2 1 2 1 2 1 8 9 10
这就是我们说的memcpy这个函数一旦重叠,它返回的结果就是错的
所以,对于重叠的内存,应该交给memmove来处理,这就引出我们下面要讲的这个函数了
二.memmove使用和模拟实现
我们发现,memmove的参数与memcpy没有任何的区别
所以对于重叠的情况,我们只需要将上面代码的 my_memcpy(arr1+2, arr1, 5 * sizeof(int));
改成memmove(arr1+2, arr1, 5 * sizeof(int));就能完成任务了
我们来打印一下:
我们发现,打印出来的结果正是我们想要的
我们来总结一下
如果source和destination没有有任何的重叠,我们就用memcpy来进行拷贝
如果source和destination有重叠,我们就用memmove来进行拷贝
现在我们来模拟实现一下这个函数
void* my_memmove(void* dest, const void* src, size_t num)
//我们的想法:对于不同的情况分为从前—>后拷贝或者后—>前拷贝就可以防止覆盖~
{
void* ret = dest;
assert(dest && src);
if (dest < src)
{
//前->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前:src<dest<(char*)src+num
// dest>(char*)src+num时,前->后 ,后->前都可以,这里就用后->前了
while (num--)
{
*((char*)dest+num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);// 1 2 1 2 3 4 5 8 9 10
}
return 0;
}
三.memset函数的使用
memset()函数的功能是内存设置
ptr是设置的内存从哪开始,value是内存设置的值是什么,num是要设置几个字节
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容
下面是一个例子:
int main()
{
char arr[10] = "hello world";
memset(arr, 'x', 5);
//memset 在设置的时候,是以字节为单位来设置的
printf("%s\n", arr);
return 0;
}
四.memcmp函数的使用
它与strcmp非常类似,我们直接来看一个例子:
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[] = { 1,2,3,4,8 };
int ret = memcmp(arr1, arr2, 16);
printf("%d\n", ret);
return 0;
}
运行结果如下:(注意:这里的num也是以字节为单位的)
结语
好了,今天的分享就到这里了
在学习C语言的道路上Humble与各位同行,加油吧各位!
最后希望大家点个免费的赞或者关注吧(感谢感谢)
让我们在接下来的时间里一起成长,一起进步吧!