内存函数 memcpy 和 memmove 的讲解和模拟实现

简介: 内存函数 memcpy 和 memmove 的讲解和模拟实现

一.什么是 memcpy 函数

我们打开 cplusplus 官网查看:

memcpy - C++ Reference (cplusplus.com)

官方文本显示:


内存复制块

  • 将 num 字节的值从源指向的位置直接复制到目标指向的内存块
  • 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本
  • 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节
  • 为了避免溢出,目标参数和源参数所指向的数组的大小应该至少为 num 字节,并且不应该重叠(对于重叠的内存块,memmove 是一种更安全的方法)

上述文本可能不够直观,我们使用官方提供的例子观察他的具体作用:

/* memcpy example */
#include <stdio.h>
#include <string.h>
struct 
{
  char name[40];
  int age;
} person, person_copy;
int main()
{
  char myname[] = "Pierre de Fermat";
  /* using memcpy to copy string: */
  memcpy(person.name, myname, strlen(myname) + 1);
  person.age = 46;
  /* using memcpy to copy structure: */
  memcpy(&person_copy, &person, sizeof(person));
  printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
  return 0;
}

输出结果:


      结合代码和输出结果来看,我们申明了俩个结构体,并且我们手动给结构体 person 的俩个变量进行了赋值,而结构体 person_copy 我们并没有对其初始化赋值,我们使用了 memcpy 函数将结构体 person 中的值复制给了结构体 person_copy ,然后我们打印输出 person_copy 中的变量的值,发现我们确实是拿到了这俩个值

模拟思路

当我们拿到一个字符串后,首先要确定复制的起点位置和复制目标的起点位置

然后逐一复制字节

代码实现

       在这里,我们使用 void* 的指针来拿到各种数据类型的地址,然后强制转化为 char* 方便我们对单个字节进行访问(字符型指针解引用只能访问一个字节),函数参数方面,只需要拿到俩个地址加上需要复制多少个字节的大小的值就可以了

void* my_memcpy(void* dest, const void* src, size_t sz)
{
  void* ret = dest;
  assert(dest && src);
  while (sz--)
  {
    *(char*)dest = *(char*)src;
    dest = (char*)dest + 1;
    src = (char*)src + 1;
  }
  return ret;
}

二.什么是 memmove 函数

我们打开 cplusplus 官网查看:

memmove - C++ Reference (cplusplus.com)

官方文本显示:

移动内存块

将 num 字节的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,从而允许目标和源重叠

源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本

该函数不检查源中是否有任何终止 null 字符——它总是精确地复制 num 个字节

为了避免溢出,目的参数和源参数所指向的数组的大小至少为 num 字节


上述文本可能不够直观,我们使用官方提供的例子观察他的具体作用:

/* memmove example */
#include <stdio.h>
#include <string.h>
int main ()
{
  char str[] = "memmove can be very useful......";
  memmove (str+20,str+15,11);
  puts (str);
  return 0;
}

输出结果:

     我们可以看见,原本的字符串是 memmove can be very useful...... 但是输出的却是 memmove can be very useful. 也就是我们将后半部分的 very useful 往后移动了一段距离


模拟思路

       在模拟实现这个功能之前,有一点值得注意,相较于之前的 memcpy 函数,这里的 memmove 函数在移动的时候,内部是有重复部分的,如果还是按照上面那种方法实现的话,会出现数据反复覆盖导致丢弃了真实数据的情况,如图所示


对于这个情况,我们换一个交换字节的顺序就可以解决,如图


    也就是说,我们只需要做出合理的判断,选择正确的顺序,就可以实现功能,根据我们的经验,如果我们要实现的是从前往后移动拷贝的话,那我们就从后往前访问,反之,如果我们要从后往前移动拷贝的话,那我们就从前往后访问


代码实现

void* my_memmove(void* dest, const void* src, size_t sz)
{
  assert(dest && src);
  void* ret = dest;
  if (dest < src)
  {
    //前->后
    int i = 0;
    for (i = 0; i < sz; i++)
    {
      *(char*)dest = *(char*)src;
      dest = (char*)dest + 1;
      src = (char*)src + 1;
    }
  }
  else
  {
    //后->前
    while (sz--)
    {
      *((char*)dest+sz) = *((char*)src + sz);
    }
  }
  return ret;
}

本次分享就到此为止了,如有错误欢迎积极指出,希望我的分享能给您带来帮助

目录
相关文章
|
3月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
44 3
|
1月前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
64 6
|
3月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
3月前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
43 0
|
3月前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
50 0
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
356 1
|
29天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
2月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
25 3
|
2月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
55 1

热门文章

最新文章