详解内存操作函数

简介: 详解内存操作函数

前言

者:小蜗牛向前冲

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

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




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

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函数可能并不一定试用于数组内容的初始化(大家可以动手试试)。

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



相关文章
|
11天前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)
TU^
|
3天前
|
C语言
C语言内存函数和字符串函数模拟实现
C语言内存函数和字符串函数模拟实现
TU^
9 0
|
5天前
|
编译器 C语言 C++
c语言常见字符函数、内存函数(详讲)
c语言常见字符函数、内存函数(详讲)
|
9天前
|
C语言
C语言—内存函数的实现和模拟实现(内存函数的丝绸之路)
C语言—内存函数的实现和模拟实现(内存函数的丝绸之路)
23 0
|
11天前
|
编译器 C语言
字符串与内存函数
字符串与内存函数
27 0
|
2天前
|
Java 编译器 C语言
深入了解字符(串)函数 -- -- 字符(串)函数的实现(strlen、strcpy、strcmp、strcat、strstr、)内存函数的实现(memcpy、memmove)
深入了解字符(串)函数 -- -- 字符(串)函数的实现(strlen、strcpy、strcmp、strcat、strstr、)内存函数的实现(memcpy、memmove)
9 0
|
3天前
|
C语言
c语言内存函数
c语言内存函数
10 0
|
3天前
|
C语言
c语言:字符串和内存函数介绍-2
c语言:字符串和内存函数介绍
6 0
|
3天前
|
C语言
c语言:字符串和内存函数介绍-1
c语言:字符串和内存函数介绍
10 0
|
4天前
|
安全 编译器 C语言
【C语言】字符串和内存函数的介绍 -- 详解
【C语言】字符串和内存函数的介绍 -- 详解