10分钟让你学会内存函数:memcpy,memmove,memset,memcmp的用法及模拟实现。

简介: 10分钟让你学会内存函数:memcpy,memmove,memset,memcmp的用法及模拟实现。

目录:内存操作函数

一:memcpy函数(内存拷贝)

二:memmove函数(内存拷贝)

三:memset函数(内存设置)

四:memcmp函数(内存比较)


一:memcpy函数

memcpy内存函数的实现原理:                                                                                                    

将 num 个字节的数据从 source 指向的位置开始拷贝到 destination 指向的内存块中,这个函数在遇到0’的时候并不会停下

所以memcpy函数中需要传入三个参数,分别是目标内存空间的首地址,被拷贝内存空间的首地址和拷贝字节数。

memcpy函数可以拷贝字符串数据,整形数组数据,结构体数据等诸多类型......,但因为memcpy内存函数不能够自身拷贝,memcpy函数不能够拷贝内存重叠区的数据,因此存在着一定的局限性,在这里,小夏推荐大家在遇到数据拷贝时应用接下来的memmove函数可以完美的避免所有的不稳定因素。


二:memmove函数

memmove内存函数的实现原理(内存存在重叠,无重叠都可使用):

用于拷贝内存数据,如果目标区域和源区域有重叠的话,

memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中

但复制后源内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同

memmove函数实现重叠内存过程:

总结来说,在遇到内存重叠的情况下分为三中情况:

1.从前向后拷贝(内存空间存在重叠)->如果source的地址高于disnation的地址:则进行常规的赋值,及从source的地址依次向后对disnation地址进行拷贝,直到拷贝的字节数达到size_t num,及拷贝完成。

2.从后向前拷贝(内存空间存在重叠)->如果source的地址低于disnation的地址:则进行逆序的赋值,及从source+num的地址向前对disnation+num地址进行拷贝,直到拷贝的字节数达到size_t num,及拷贝完成。

3.从前向后拷贝或-从后向前拷贝都可(内存空间不存在重叠)


模拟实现memmove函数:

我们可以自己写一个my_memmove函数来模拟实现memmove函数的功能

首先定义函数void* my_memmove(void* s1, const void* s2, size_t len)

因为memmove是拷贝内存的函数,对于内存中被拷贝的是什么数据类型,并没有限制,所以传入的参数数据类型用void*,返回值也是无类型的地址。

size_len是一个无符号整数类型,表示想要拷贝的字节数,所以在my_memmove函数内部,我们可以这样写

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* s1, const void* s2, size_t len)
{
  assert(s1);
  assert(s2);
  void* ret = s1;
  int i = 0;
  
  if (((char*)s2)>((char*)s1))//从s2的前端依次拷贝
  {
    for(i=0;i<len;i++)
    {
      *((char*)s1) = *((char*)s2);
      (char*)s1 = (char*)s1 + 1;
      (char*)s2 = (char*)s2 + 1;
    }
  }
  else
  {
    while (len--)//从s2的后端开始拷贝
      {
        *((char*)s1 + len) = *((char*)s2 + len);
      }
  }
 
  return ret;
}
int main()
{
  
  int arr[20] = { 0 };
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    arr[i] = i + 1;
  }
  my_memmove(arr + 1, arr , sizeof(int) * 5);
  for (i = 0; arr[i] != 0; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}


三:memset函数

memset内存函数的实现原理:num字节对内存块进行初始化

将value的值依次从ptr地址,依次向后size_t num个字节的内存空间进行赋值


memset的函数定义:

模拟实现memset函数:

我们可以自己写一个my_memset函数来模拟实现memset函数的功能

首先定义函数void* my_memset(void * ptr, int value, size_t num)

因为memset是拷贝内存的函数,对于内存中被拷贝的是什么数据类型,并没有限制,所以传入的参数数据类型用void*,返回值也是无类型的地址。

size_num是一个无符号整数类型,表示想要赋值的字节数,所以在my_memset函数内部,我们可以这样写

#include<stdio.h>
void* my_memset(void* ptr, int value, size_t num)
{
  while (num--)
  {
    *((char*)ptr) = value + '0';
    ptr = (char*)ptr + 1;
  }
}
int main()
{
  char arr[] = "abcdefghijk";
  my_memset(arr+1, 6, 3);
  printf("进过赋值后的结果->%s\n", arr);
  return 0;
}

在模拟实现memset函数中有一个小小的知识点就是:将数字转化成字符该如何转化,字符‘0’的ASCLL值为48,数字0的ASCLL值为0,所以将数字加上字符‘0’就可得到相应的字符

该函数实现的结果为:


四:memcmp函数

memcmp内存函数的实现原理:用于比较比较内存的前N个字节

字符串大小的比较是以ASCII 码表上的顺序来决定,次顺序亦为字符的值。memcmp()首先将s1 第一个字符值减去s2 第一个字符的值,若差为0 则再继续比较下个字符,若差值不为0 则将差值返回。

两个字符串内容完全一样,返回0;

若S1大于S2,则大于0,

反之则小于0;

memcmp的函数定义:从ptr1内存空间和ptr2内存空间依次向后进行比较size_t num个字节大小,且per1和ptr2进const修饰不可改变其内容。


模拟实现memcmp函数:

我们可以自己写一个my_mecmp函数来模拟实现memcmp函数的功能

首先定义函数void* my_memcmp(const void*ptr1,const void*ptr2,size_t num)

#include<stdio.h>
void* my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
  while (num--)
  {
    if (*(char*)ptr1 == *(char*)ptr2)
    {
      ptr1 = (char*)ptr1 + 1;
      ptr2 = (char*)ptr2 + 1;
    }
    else
    {
      return *(char*)ptr1 - *(char*)ptr2;
    }
  }
}
int main()
{
  char s1[] = "abcd456ef";
  char s2[] = "abef789nmn";
  int ret=my_memcmp(s1, s2, 5);
  printf("差值为->%d", ret);
 
  return 0;
}

其执行结果为:

执行结果:

my_memcmp(s1+7, s2,5):1 //字符串s1>字符串s2, 返回正值

my_memcmp(s1, s2,5):-1 // 字符串s1<字符串s2,返回负值

my_memcmp(s1, s2,2):0 //字符串s1=字符串s2, 返回0


如果觉得文章不错,期待你的一键三连哦,你个鼓励是我创作的动力之源,让我们一起加油,顶峰相见!!!

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