详解内存操作函数

简介: 详解内存操作函数

前言

者:小蜗牛向前冲

名言:我可以接收失败,但我不能接收放弃

如果觉的博主的文章还不错的话,还请 点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。




这次主要为大家分析内储操作函数的使用。

memcpy内存拷贝函数

该函数主要用来拷贝各类型的数据。

参数

我们要传给该函数的参数有:

dest:指向要在其中复制内容的目标数组的指针,类型转换为 void* 类型的指针。

src:指向要复制的数据源的指针,类型转换为 const void* 类型的指针。

num:要复制的字节数,size_t是无符号整数类型。

头文件

#include <string.h>

下面进行代码演示:

#define  _CRT_SECURE_NO_WARNINGS
 
#include<stdio.h>
#include<string.h>
int main()
{
  int arr1[] = { 1,2,3,4,5 };
  int arr2[10] = { 0 };
  memcpy(arr2, arr1, sizeof(arr1));
  return 0;
}

从上面代码我们可以看出,拷贝整形成功,那么mencpy到底是如何拷贝的呢?为什么strcpy函数就仅仅只能拷贝字符串,而memcpy却能够拷贝所有的内存数据呢?

首先我可以告诉大家,memcpy是对内存中的数据进行一个一个字节进行拷贝的。

其次,strcpy的拷贝方式是让数组中的字符直接经行交换,所以这样整形,浮点型,结构体都不可以进行拷贝。

那么,由于mencpy函数是一个一个字节进行拷贝的,而所有的内存单元都是由字节组成,内存的最小单位是1个字节,所以当mencpy函数进行一个一个字节进行拷贝,能够拷贝所有的内存单元。

基本上面对mencpy函数内存拷贝方式的理解,下面我们进行该函数实现的模拟。

memcpy函数的模拟实现

void* my_memcpy(void* dest, const void* src, size_t num)
{
  assert(dest && src);//断言
  char* start =(char*)dest;//标记目标数组的地址
  //一个一个字节进行拷贝
  while (num--)
  {
    *(char*)dest = *(char*)src;
    ++(char*)dest;
    ++(char*)src;
  }
  return start;
}

当我们实现完memcpy函数,这个函数真的能够拷贝所有的内存数据吗?

下面继续看:

void* my_memcpy(void* dest, const void* src, size_t num)
{
  assert(dest && src);//断言
  char* start =(char*)dest;//标记目标数组的地址
  //一个一个字节进行拷贝
  while (num--)
  {
    *(char*)dest = *(char*)src;
    ++(char*)dest;
    ++(char*)src;
  }
  return start;
}
 
int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10};
  //int arr2[10] = { 0 };
     my_memcpy(arr1+3, arr1, 20);
  return 0;
}

本来按理来说arr1拷贝完的结果为{1,2,3,1,2,3,4,5,9,10};但实际结果是:

为什么会出现这种状况呢?

这是和我们的memcpy的实现方法有关,我们是从前向后拷贝的,但是这样就会造成一个问题,当源内存块和目标内存块是重叠时,我们在拷贝前面的内存时后面的内存也会改变,这样就会使得拷贝失败。专门写了用来拷贝源内存块和目标内存块是重叠时这种情形的函数memmove。

memmove函数

其实我们从函数的定义是看,memmove和memcpy都是相同的,但不同的是memmove函数可以处理源内存块和目标内存块是重叠的情形。

参数

二者参数都是相似的,这里就不在多说,下面我们要讨论一下,源内存块和目标内存块是重叠的不同情形。

情形1(dest)

我们都是一个一个字节拷贝的,但怎么才能实现内存拷贝呢?,如果是情形1我们只有进行从前-->后拷贝就可实现(memcpy的实现方式)

情形2(dest>src&&dest

如果是情形2如果我们仍然是从前-->后拷贝,这样就会出现数据覆盖的现象,但我们可以从后-->前拷贝就可以避免数据覆盖。

情形3(dest>scr+num)

如果是发现情形3的情形,既然目标空间都和内存空间都不重叠了,那么拷贝的方式无论是从前-->后或者从后-->前都是可以的。

我们理解上面的三种拷贝情况,我们继续举例说明一下memmove函数的功能。

为了更好的理解menmove函数的功能,下面我们模拟实现。

//模拟实现memmove
void* my_memmove(void* dest, const void* src, size_t num)
{
  assert(dest && src);//断言
  char* start = (char*)dest;
  if (dest < src)
  {
    while (num--)
    {
      *(char*)dest = *(char*)src;
      ++(char*)dest;
      ++(char*)src;
    }
  }
  else
  {
    while (num--)
    {
      *((char*)dest + num) = *((char*)src + num);
    }
  }
  return start;
}

memcmp内存拷贝函数

我们前面学习了,字符拷贝函数,下面我们来见识一下内存拷贝函数吧!

该函数是用来比较两个内存块

参数

ptr1:

指向内存块的指针。

ptr2:

指向内存块的指针。

num:

要比较的字节数。

返回值

该函数返回一个整数值,指示内存块内容之间的关系:

<0:

在两个内存块中不匹配的第一个字节在 ptr1 中的值低于在 ptr2 中的值

0:

两个内存块的内容相等

>0:

在两个内存块中不匹配的第一个字节在 ptr1 中的值大于在 ptr2 中的值

代码举例:

int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
  int arr2[10] = { 1,2,3,4,6 };
  int ret = memcmp(arr1, arr2, 20);
  if (ret > 0)
  {
    printf("前20字节数中在两个内存块中不匹配的第一个字节在arr1中的值>arr2中的值\n");
  }
  else if(ret<0)
  {
    printf("前20字节数中在两个内存块中不匹配的第一个字节在arr1中的值<arr2中的值\n");
  }
  else
  {
    printf("两个内存块的内容相等\n");
  }
  
  return 0;
}

memset内存设置函数

有时候我们需要对内存中值经行修改,就可以用到memset函数。

参数

ptr:

指向要填充的内存块的指针。

value:

要设置的值。该值作为 int 传递,但该函数使用此值的无符号 char 转换来填充内存块。

num:

要设置为该值的字节数。

size_t是无符号整数类型。

返回值

代码举例:

int main()
{
  char mane[20] = "Xiao  ming";
  memset(mane + 5, '*', 1);//设置内存
  printf("%s", mane);//打印
  return 0;
}

那么我们可以用memset对数组初始化吗?

大家可以看到,我本意(误用)是想把arr的内容都初始化为1,但却最后初始化的值并不是我想要的结果,为什么呢?

原来是我对memset的函数的理解不到位,该函数是一个字节一个字节进行设置的,而不是直接设置一个整形。

所以在数组中设置的第1元素其实是01 01 01 01(十六进制,一个字节=8bit位)。其实用memset初始化数组也是可以,但是比较麻烦,所以还是要慎重使用。

好了就分析这些内存函数,下面对本篇博主的重点进行简单总结。

总结

memcpy函数是用来进行内存拷贝的,但要注意C语言规定:该函数只要能拷贝内存不重叠的内存即可,但在有些编译器中也是可以拷贝内存重叠的内存的。(如VS)

memmove是C语言用来拷贝内存重叠的内存的。

memcmp可以比较两个内存块。

memset函数可能并不一定试用于数组内容的初始化(大家可以动手试试)。

大家喜欢的来个三连支持博主吧!



相关文章
|
29天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
21天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
135 1
|
1月前
|
程序员 C语言
C语言内存函数精讲
C语言内存函数精讲
|
5月前
|
C语言
【C语言】:动态内存管理函数malloc,calloc,realloc和free的介绍的介绍
【C语言】:动态内存管理函数malloc,calloc,realloc和free的介绍的介绍
62 0
|
16天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
15 0
|
30天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
39 0
|
1月前
|
存储 C语言 C++
来不及哀悼了,接下来上场的是C语言内存函数memcpy,memmove,memset,memcmp
本文详细介绍了C语言中的四个内存操作函数:memcpy用于无重叠复制,memmove处理重叠内存,memset用于填充特定值,memcmp用于内存区域比较。通过实例展示了它们的用法和注意事项。
62 0
|
1月前
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
60 0