模拟实现一些库函数(2)(上)

简介: 模拟实现一些库函数(2)(上)

函数介绍

本章内容给大家展示一些内存操作函数

memcpy

memmove

memset

memcmp

给大家讲解该函数,并实现模拟

memcpy

函数讲解

memcpy函数是C语言中的一个标准库函数,用于在内存之间进行数据复制。它的函数原型如下:

void *memcpy(void *destination, const void *source, size_t num);

memcpy函数的作用是将源内存块中的数据复制到目标内存块中,复制的字节数由num指定。

destination是目标内存块的指针,指向要将数据复制到的位置。

source是源内存块的指针,指向要复制数据的起始位置。

num指定要复制的字节数。

注意,memcpy函数的参数类型为void*,这意味着它可以复制任意类型的数据。

memcpy函数的工作原理是按字节复制。它从源内存块中以字节为单位逐一复制数据,并将其存储到目标内存块中。这就是为什么需要指定要复制的字节数,以确保复制的范围正确。

值得注意的是,memcpy函数不能处理内存重叠的情况。如果源内存块和目标内存块有重叠部分,使用memmove函数会更安全,它可以正确处理这种情况。

接下来我们代码示例,来看一下该函数效果:

int main() {
    int arr1[10] = { 0 };
    int arr2[] = { 32,23,14,22,5 };
    memcpy(arr1, arr2, 20);  
    for (int i = 0; i < +5; i++)
    {
        printf("%d  ", arr1[i]);
    }
    return 0;
}

这个函数和strcpy的区别在于strcpy只可以拷贝字符串类型,而memcpy函数可以拷贝任何类型的数据

模拟实现

接下来我们来模拟实现一下

void* my_memcpy(void* arr1, const void* arr2, size_t size)
{
    void* ret = arr1;
    assert(arr1 && arr2);
    size_t i = 0;
    while (i < size)
    {
        *(char*)arr1 = *(char*)arr2;
        arr1 = (char*)arr1 + 1;
        arr2 = (char*)arr2 + 1;
        i++;
    }
    return ret;
}
int main() {
    int arr1[10] = { 0 };
    int arr2[] = { 32,23,14,22,5 };
    my_memcpy(arr1, arr2, sizeof(arr2));
    for (int i = 0; i < 5; i++)
    {
        printf("%d  ", arr1[i]);
    }
    return 0;
}

接下来,来具体分析一下模拟的memcpy函数,首先他的返回值是指向目标内存的地址,所以我们设置ret来记录其实位置的地址,同时用assert函数来保证传入的arr1指针和arr2指针非空,之后进入我们的复制循环中,由于该函数是一个字节一个字节的访问,所以才循环内部,我们把arr2强转为char类型后解引用,赋值给arr1强转为char 后解引用,在这里我们不能使用

(char)arr1++ = (char)arr2++;

的原因是++的优先级高,所以如果使用的话,arr1就会跳过以传入数据的字节,也就是4个字节,之后才强转为char* 进行操作,并不会一个一个字节的操作,所以我们不使用这个代码,我们直接把arr1强转为char*后进行+1操作在赋值给arr1,同理arr2进行同样的操作。这样就可以一个字节一个字节的进行操作了。

memmove

函数讲解

刚刚在介绍memcpy时我们提到了,memcpy不能处理内存重叠的情况,而memmove可以,那么我们就来介绍一下memmove。

memmove 是 C/C++ 标准库中的一个函数,用于在内存中移动一定数量的字节数据。

memmove 函数的函数原型如下:

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

参数解释如下:

dest:目标内存块的指针,表示要移动数据的目标位置。

src:源内存块的指针,表示要从其中复制数据的起始位置。

n:要移动的字节数,即要复制的数据大小。

memmove 函数的功能是将 src 所指向的内存块中的数据复制到 dest 所指向的内存块中,同时保证当 src 和 dest 内存块重叠时也能正常执行。

相比于另一个相关的函数 memcpy,memmove 函数在处理内存块重叠的情况下更为安全,因为它会根据内存块的重叠情况自动选择正确的数据复制方式。这意味着 memmove 函数即使在源和目标内存块重叠的情况下,也可以正确地进行数据复制,而不会导致数据损坏。

介绍完成后我们来看一下该函数的效果。

int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8 };
  memmove(arr1, arr1 + 2, 8);
  for (int i = 0; i < 8; i++)
  {
    printf("%d  ", arr1[i]);
  }
  return 0;
}

模拟实现

那么接下来我们来模拟实现一下该函数

void* my_memmove(void* dest,const void* src, size_t num)
{
  void* ret = dest;
  assert(dest && src);
  size_t i = 0;
  if (dest < src)
    {
    while (i < num)
    {
      *(char*)dest = *(char*)src;
      dest = (char*)dest + 1;
      src = (char*)src + 1;
      i++;
    }
    }
  else
    {
    while (num--)
    {
      *((char*)dest + num) = *((char*)src + num);
    }
    }
  return ret;
}
int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8 };
  my_memmove(arr1+2, arr1, 8);
  for (int i = 0; i < 8; i++)
  {
    printf("%d  ", arr1[i]);
  }
  return 0;
}

对于内存重叠的情况无非就是dest<src和dest>src两种情况,dest<src的情况呢,其实和memcpy差不多,所以在这里我们不再过多赘述,我们只了解一下dest>src的情况,首先如果dest>src的话会出现覆盖的现象,所以我们从后面往前面赋值,直接把dest和src强转为char*然后加上num个字节数,从后面往前面赋值,我们直接把循环条件设置为num–,下次进入while循环直接就是从倒数第一个字节到了倒数第二个字节,实现了一个字节一个字节操作的编程行为。

目录
相关文章
|
6月前
|
C语言
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
|
6月前
|
C语言
C语言-----qsort函数的功能以及模拟实现
C语言-----qsort函数的功能以及模拟实现
55 1
|
6月前
|
存储 C语言
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))
111 0
|
6月前
|
存储 安全 C语言
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))
123 0
|
C语言
C语言常见库函数的模拟实现
C语言常见库函数的模拟实现
57 0
|
C语言
【进阶C语言】字符串与内存库函数认识与模拟实现(1)
size_t为无符号整形,接受他的返回值的变量类型也应该为size_t 函数参数就是字符指针类型。const为了修饰*str,防止原字符串的数据被修改。 需要包含的头文件为:#include&lt;string.h&gt;
56 0
|
1月前
|
C语言
初识C语言3——函数(以猜数字游戏为例)
初识C语言3——函数(以猜数字游戏为例)
65 0
|
6月前
|
C语言 存储
C语言—部分库函数的模拟实现
C语言—部分库函数的模拟实现
|
6月前
|
算法
库函数讲解及模拟实现库函数
库函数讲解及模拟实现库函数
23 0
|
存储 编译器 C语言
【进阶C语言】字符串与内存库函数认识与模拟实现(2)
size_t为无符号整形,接受他的返回值的变量类型也应该为size_t 函数参数就是字符指针类型。const为了修饰*str,防止原字符串的数据被修改。 需要包含的头文件为:#include&lt;string.h&gt;
76 0