模拟实现一些库函数(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循环直接就是从倒数第一个字节到了倒数第二个字节,实现了一个字节一个字节操作的编程行为。

目录
打赏
0
0
0
0
0
分享
相关文章
Ubuntu18.04 Install Node.js Np
Ubuntu18.04 Install Node.js Np
216 0
大数据& AI 产品月刊【2025年3月】
大数据& AI 产品技术月刊【2025年3月】,涵盖3月技术速递、产品和功能发布、市场和客户应用实践等内容,帮助您快速了解阿里云大数据& AI 方面最新动态。
Flink CDC + Hologres高性能数据同步优化实践
本文整理自阿里云高级技术专家胡一博老师在Flink Forward Asia 2024数据集成(二)专场的分享,主要内容包括:1. Hologres介绍:实时数据仓库,支持毫秒级写入和高QPS查询;2. 写入优化:通过改进缓冲队列、连接池和COPY模式提高吞吐量和降低延迟;3. 消费优化:优化离线场景和分区表的消费逻辑,提升性能和资源利用率;4. 未来展望:进一步简化用户操作,支持更多DDL操作及全增量消费。Hologres 3.0全新升级为一体化实时湖仓平台,提供多项新功能并降低使用成本。
414 1
Flink CDC + Hologres高性能数据同步优化实践
阿里云实时计算Flink在多行业的应用和实践
本文整理自 Flink Forward Asia 2023 中闭门会的分享。主要分享实时计算在各行业的应用实践,对回归实时计算的重点场景进行介绍以及企业如何使用实时计算技术,并且提供一些在技术架构上的参考建议。
1221 7
阿里云实时计算Flink在多行业的应用和实践
Hologres V2.1版本发布,新增计算组实例构建高可用实时数仓
新增弹性计算组实例,解决实时数仓场景下分析性能、资源隔离、高可用、弹性扩缩容等核心问题,同时新增多种用户分析函数与实时湖仓Paimon格式支持,COUNT DISTINCT优化显著提升查询效率。
阿里云中间件有哪些?这里最全面
这其实是一个比较虚的概念。广义的中间件范围很广。起沟通作用的都可以认为是中间件。甚至ODBC这样的东西你也可以认为是中间件。 而阿里云的中间件就比较多了
9535 76
钱大妈基于 Flink 的实时风控实践
钱大妈与阿里云 Flink 实时计算团队共建实时风控规则引擎,精确识别羊毛党以防营销预算流失。
钱大妈基于 Flink 的实时风控实践
Flink Native Kubernetes实战
Flink Native Kubernetes是1.10版本才有的新功能,通过bin目录下的工具控制kubernetes环境下的flink操作
2209 0
Flink Native Kubernetes实战
查询性能优化之Runtime Filter
在分析类查询中,大表之间(或大表与小表)的 Join 通常使用 Hash Join 实现,这通常也是查询的性能瓶颈之一,因此如何优化join的查询性能也是计算引擎的重点。
1872 0
查询性能优化之Runtime Filter
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问