C语言内存函数

前言

上篇博客我们分析了字符函数和字符串函数,这篇咱们就来看看内存函数

个人主页:小张同学zkf

若有问题,评论区见

感兴趣就关注一下吧

 


目录

 1. memcpy使用和模拟实现

 2. memmove使用和模拟实现

 3. memset函数的使用

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感谢观看


 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-18 18:20:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-18 18:20:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-18 18:20:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-18 18:20:01       18 阅读

热门阅读

  1. 5.66 BCC工具之offwaketime.py解读

    2024-03-18 18:20:01       15 阅读
  2. 备份恢复新体验!pgBackRest与IvorySQL的完美融合

    2024-03-18 18:20:01       18 阅读
  3. Spring概述总结

    2024-03-18 18:20:01       20 阅读
  4. Linux的内存计算不准如何解决?

    2024-03-18 18:20:01       18 阅读
  5. LLM大模型统一封装接口解决方案

    2024-03-18 18:20:01       21 阅读
  6. VTK中GetOutputPort()和GetOutput()的区别

    2024-03-18 18:20:01       21 阅读
  7. 【Educoder数据挖掘实训】用Cosine计算相似度

    2024-03-18 18:20:01       18 阅读