内存函数(memcpy、memmove、memset、memcmp)你真的懂了吗?

简介: 内存函数(memcpy、memmove、memset、memcmp)你真的懂了吗?


前言

当我们谈论内存函数时,我们在讨论什么呢?简单来说,内存函数是用于处理和操作内存的函数。这些函数在程序运行期间分配、释放和操作内存,对于程序的性能、效率和稳定性至关重要。在编程语言的发展历程中,内存函数始终占据着重要的地位,尤其是在现代编程中,它们的意义更为突出。

本文将深入探讨内存函数的相关知识,旨在帮助读者更好地理解这一领域,并提高在现代编程中的技能。

头文件<string.h>

🎄1.memcpy 函数

声明

void *memcpy(void *dest, const void *src, size_t num);

参数

  • dest - - - 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • src - - - 指向要复制的数据源,类型强制转换为 void* 指针。
  • num - - - 要被复制的字节数。

返回值

  • 该函数返回一个指向目标存储区 dest 的指针。

1.1【注意事项】:

  • C 库函数 void *memcpy(void *dest, const void *src, size_t num) 从存储区 src 复制 num 个字节到存储区 dest
  • 函数memcpysrc的位置开始向后复制num个字节的数据到dest的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果 srcdest 有任何的重叠,复制的结果都是未定义的。

1.2【实例】

/* 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;
}

🔎memcpy 的模拟实现

//模拟实现memcpy
#include<stdio.h>
#include<assert.h>
 //不重叠内存的拷贝可以使用memcpy
void* my_memcpy(void* dest,const void* src, size_t sz)
{
  assert(dest && src);
  void* ret = dest;
  while (sz--)
  {
    //因为不知道要拷贝到数据类型,所以一个字节一个字节的拷贝
    *(char*)dest = *(char*)src;
    //强制类型转换是临时的,不能写成(char*)dest++,且++的优先级更高,void*类型指针不能加减操作
    dest = (char*)dest + 1;
    src = (char*)src + 1;
  }
  return dest;
}
int main()
{
  int arr1[10] = { 0 };
  int arr2[] = { 1,2,3,4,5 };
  my_memcpy(arr1, arr2, 20);
  for (int i = 0; i < 5; i++)
  {
    printf("%d ", arr1[i]); //结果是 1 2 3 4 5
  }
  printf("\n");
}

🎄2.memmove 函数

声明

void *memmove(void *dest, const void *src, size_t num);

参数

  • dest - - - 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • src - - - 指向要复制的数据源,类型强制转换为 void* 指针。
  • num - - - 要被复制的字节数。

返回值

  • 该函数返回一个指向目标存储区 dest 的指针。

2.1【注意事项】:

  • C 库函数 void *memmove(void *dest, const void *src, size_t num)src 复制 num 个字符到 dest,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

2.2【实例】

/* 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 的模拟实现

//模拟实现memmove
#include<stdio.h>
#include<assert.h>
//重叠内存的拷贝,使用memmove
void* my_memmove(void* dest, void* src, size_t sz)
{
  assert(dest && src);
  void* ret = dest;
  if (dest < src)
  {
    //前 -> 后
    while (sz--)
    {
      *(char*)dest = *(char*)src;
      dest = (char*)dest + 1;
      src = (char*)src + 1;
    }
    /*for (int 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;
}
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  my_memmove(arr, arr + 2, 20);
  for (int i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}

🎄3.memset 函数

声明

void *memset(void *ptr, int value, size_t num);

参数

  • ptr - - - 指向要填充的内存块。
  • value - - - 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
  • num - - - 要被设置为该值的字符数。

返回值

  • 该值返回一个指向存储区 ptr 的指针。

3.1【注意事项】:

-C 库函数 void *memset(void *ptr, int value, size_t num) 复制字符 value(一个无符号字符)到参数 ptr 所指向的字符串的前 num 个字符。

3.2【实例】

#include <stdio.h>
#include <string.h>
int main ()
{
   char str[50];
   strcpy(str,"This is string.h library function");
   puts(str);
   memset(str,'$',7);
   puts(str);
   return(0);
}

🎄4.memcmp 函数

声明

int memcmp(const void *ptr1, const void *ptr2, size_t num);

参数

  • ptr1 - - - 指向内存块的指针。
  • ptr2 - - - 指向内存块的指针。
  • num - - - 要被比较的字节数。

返回值

  • 如果返回值 < 0,则表示 ptr1 小于 ptr2
  • 如果返回值 > 0,则表示 ptr1 大于 ptr2
  • 如果返回值 = 0,则表示 ptr1 等于 ptr2

4.1【注意事项】:

  • C 库函数 int memcmp(const void *ptr1, const void *ptr2, size_t num)) 把存储区 ptr1 和存储区 ptr2 的前 num 个字节进行比较。

4.2【实例】

代码1:

/* memcmp example */
#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;
}

代码2:

#include <stdio.h>
#include <string.h>
int main()
{
  char str1[15];
  char str2[15];
  int ret;
  memcpy(str1, "abcdef", 6);
  memcpy(str2, "ABCDEF", 6);
  ret = memcmp(str1, str2, 5);
  if (ret > 0)
  {
    printf("str1 大于 str2\n");
  }
  else if (ret < 0)
  {
    printf("str1 小于 str2\n");
  }
  else
  {
    printf("str1 等于 str2\n");
  }
  return(0);
}

🔥今天的分享就到这里, 如果觉得博主的文章还不错的话, 请👍三连支持一下博主哦🤞

目录
相关文章
|
21天前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
49 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`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
40 0
|
28天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
232 1
|
18天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
27天前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
28天前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
21 3
|
28天前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
45 1
|
1月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
80 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS