库函数的模拟实现(memcpy)

一、memcpy函数说明

还是老惯例,cplusplus的网址在这里啦,家人们保存好哟!

函数总结:

  1. 功能

    • 将 num 字节的数据从 source 指向的位置直接复制到 destination 指向的内存块。
  2. 直接复制

    • 数据复制是直接进行的,没有使用中间缓冲区。
  3. 数据类型无关性

    • 函数在复制数据时不关心 source 和 destination 指针所指向对象的底层类型。
  4. 二进制复制

    • 数据以二进制形式复制,不检查 source 中是否有终止空字符(null terminator)。
  5. 不检查溢出

    • 函数不检查目标数组是否有足够的空间,因此调用者需要确保目标数组足够大。
  6. 内存重叠问题

    • 如果 destination 和 source 指向的内存区域有重叠,使用 memcpy 可能会导致数据损坏。在这种情况下,应使用 memmove,库函数的模拟实现(memmove)
  7. 参数类型

    • destination 是指向目标数组的指针,类型转换为 void*
    • source 是指向要复制的数据源的指针,类型转换为 const void*
    • num 是要复制的字节数,类型为 size_t(无符号整型)。
  8. 返回值

    • 函数返回 destination 指针。
  9. 内存大小要求

    • 为了避免溢出,destination 和 source 指向的数组的大小至少应该是 num 字节,且这两个数组不应该重叠。
  10. 错误处理

    • 函数本身不进行错误检查,因此调用者需要确保传入的参数有效,且内存区域足够大以容纳复制的数据。

使用 memcpy 时,开发者需要确保提供的内存区域大小合适,并且正确处理任何可能的内存重叠问题,以避免数据损坏或程序崩溃。如果内存区域可能重叠,应优先使用 memmove 函数。

二、memcpy函数使用

为了让大家更加了解这个函数我们现在来使用一下

#include <stdio.h>
#include <string.h> // 包含memcpy函数的头文件

int main() {
    // 定义两个整型数组
    int sourceArray[] = {10, 20, 30, 40, 50};
    int destinationArray[5] = {0}; // 初始化为0

    // 使用memcpy从sourceArray复制5个int大小的数据到destinationArray
    memcpy(destinationArray, sourceArray, sizeof(sourceArray));

    // 打印destinationArray的内容以验证复制是否成功
    printf("Copied array elements:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", destinationArray[i]);
    }
    printf("\n");

    return 0;
}

这段代码首先包含了 string.h 头文件,这是使用 memcpy 函数所必需的。然后定义了两个整型数组 sourceArraydestinationArraysourceArray 包含了要复制的数据,而 destinationArray 是目标数组,用于存储复制的数据。

我们使用 memcpy 函数将 sourceArray 的内容复制到 destinationArray。复制的字节数是通过 sizeof(sourceArray) 计算得来的,这确保了整个数组被复制。

复制完成后,使用一个循环和 printf 函数打印 destinationArray 的内容,以验证复制操作是否成功。

 

三、memcpy模拟实现

到了本期文章的重头戏啦,我们来根据前面对函数的总结进行模拟实现吧。

#include <stdio.h>
#include <assert.h>
#include <string.h>

void* my_memcpy(void* dest, const void* src, size_t n) {
    assert(dest && src && n > 0); // 确保所有参数有效
    void* ret = dest;
    unsigned char* d = (unsigned char*)dest;
    const unsigned char* s = (const unsigned char*)src;
    for (size_t count = n; count > 0; --count) {
        *d++ = *s++;
    }
    return ret;
}

int main() {
    int a[] = {1, 2, 3};
    int b[10] = {0};
    // 使用 my_memcpy 函数复制 a 数组到 b 数组
    size_t n = sizeof(a) / sizeof(a[0]); // 计算 a 数组的元素个数
    my_memcpy(b, a, n);

    // 打印 b 数组的内容
    size_t sz = sizeof(b) / sizeof(b[0]);
    for (size_t i = 0; i < sz; i++) {
        printf("%d ", b[i]);
    }
    printf("\n");

    return 0;
}

代码详解:

  1. 自定义 my_memcpy 函数

    • 函数原型:void* my_memcpy(void* dest, const void* src, size_t n),接受三个参数,分别代表目标内存地址、源内存地址和要复制的元素个数。
    • assert(dest && src && n > 0):确保 dest 和 src 非空且 n 大于 0,这是为了确保内存复制的安全性。
  2. 函数返回值

    • void* ret = dest:保存目标地址,以便最后返回。
  3. 内存复制逻辑

    • 将 dest 和 src 转换为 unsigned char* 类型的指针,以便按字节操作。
    • 使用一个循环,从 n 开始递减至 0,每次循环中将 src 指向的字节复制到 dest 指向的位置,然后递增两个指针。
  4. 返回目标地址

    • 函数返回目标地址 ret。
  5. 使用 my_memcpy

    • 计算 a 数组的元素个数 n,并将其作为参数传递给 my_memcpy 函数,同时传递 a 和 b 的地址。这将复制 a 的内容到 b

本期内容到此结束啦,大家自己动手试试吧。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值