前言
上篇博客我们分析了字符函数和字符串函数,这篇咱们就来看看内存函数
个人主页:小张同学zkf
若有问题,评论区见
感兴趣就关注一下吧
目录
[1. memcpy使用和模拟实现](#1. memcpy使用和模拟实现)
[2. memmove使用和模拟实现](#2. memmove使用和模拟实现)
[3. memset函数的使用](#3. memset函数的使用)
[4. memcmp函数的使用](#4. memcmp函数的使用)
1. memcpy使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
这个函数有点类似于上篇博客的strncpy,但是strncpy只能拷贝字符串的,而咱们现在遇到的函数是memcpy,这个没有具体拷贝什么,它的功能就是将一个内存块里的数据拷贝到另一个内存块
注意:
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 '\0' 的时候并不会停下来。
•若这俩内存块有重叠,那复制的结果都是未定义的
我们可以看一个例子
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
这里需要强调一下,一个int类型是4个字节,那拷贝20个字节相当于将5个整形拷贝过去!!!
所以这个结果就是 把1,2,3,4,5前五个整形拷贝过来
我们来看看memcpy模拟实现
我们首先要知道第二个参数指针指向的对象不能改变,它是要拷贝的东西,其次这个函数是什么类型都能接受的,所以参数类型用void*来接受,那返回目的地的指针也是void*,然后这个函数是一个字节一个字节的拷贝,所以我们要强制转换成char*类型,因为char*解引用访问的空间就是一个字节
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
2. memmove使用和模拟实现
void * memmove ( void * destination, const void * source, size_t num );
这个函数其实只跟memcpy有一个差别,这个函数源内存块和目标内存块是可以重叠的,而memcpy不能重叠
注意:
• 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
• 如果源空间和目标空间出现重叠,就得使⽤memmove函数处理。
我们来看一下这个函数的模拟实现
这个函数我们分析一下,拷贝的时候要注意不要覆盖源内存块的内容,我么画图来看一下
这个就是覆盖上了导致不是我们想要的拷贝,这是从前向后拷贝的,从3开始向后拷贝的,那我们换个方向拷贝,从后向前拷贝试试呢
这个就没有覆盖,这个就是从后向前,就是这个是从5开始向前拷贝的,但我们再想想真的所有情况都适合于 从后向前拷贝的吗,从后想前拷贝就不会出现覆盖吗
我们来看一下这种情况
这种情况从后向前拷贝也就是从5开始向前拷贝就被覆盖了,返而这种情况从前向后拷贝不被覆盖
那我们是不是就应该总结一下,什么时候从前向后拷贝不用担心覆盖,什么时候从后向前拷贝不用担心覆盖
我们对比一下这几张图发现,目标空间首指针小于源空间的首指针时应从前向后拷贝才正常,而目标空间首指针大于源空间的首指针时,应从后向前拷贝才正常
所以if条件有了,在从后向前拷贝时记得将地址加到拷贝的最后一位
以下是代码
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
3. memset函数的使用
void * memset ( void * ptr, int value, size_t num );
这个函数就是将第一个参数的内存块设置成num个字节的第二个参数这个整形值
我们来看一下这个函数是如何使用的
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "hello world";
memset (str,'x',6);
printf(str);
return 0;
}
结果
xxxxxxworld
4. memcmp函数的使用
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较内存块里数据的大小,记住是一个一个字节比较的!!!
注意:
• 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
• 返回值如下:
我们来看看这个函数的使用
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0)
printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0)
printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else
printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}
结束语
这篇博客内存函数要和上一篇博客字符串函数区分清楚,可以对比区分一下
OK感谢观看