C memcpy() 函数

C memcpy() 语法

memcpy() 是 C 语言 <string.h> 或 <memory.h> 标准库的一个函数,它用于将 “源内存区域” 中的指定字节数复制到 “目标内存区域” 中。

语法:

memcpy(dest, src, n)

说明:

memcpy() 函数接收以下 3 个参数。

  • dest(void*):指向目标内存区域的指针。
  • src(const void*):指向源内存区域的指针。
  • n(size_t):要复制的字节数。

memcpy(dest, src, n) 会从 src 指向的内存位置开始,复制 n 个字节到 dest 指向的内存位置。复制是以 “字节” 为单位进行的,我们不需要关心源和目标内存区域中存储的数据类型。

与字符串函数(如 strcpy() 等)不同,memcpy() 不会检查或关心终止符 '\0',它只会精确地复制指定的 n 个字节。

提示:

  • memcpy 是 “memory copy” 的缩写。
  • memcpy() 函数用于 “复制” 内存中的字节,而 memset() 函数用于 “设置” 内存中的字节。

C memcpy() 摘要

使用频率
修改字符串
官方文档 查看

C memcpy() 示例

接下来,我们通过几个简单的例子来讲解一下 C memcpy() 函数是如何使用的。

示例 1:memcpy() 复制字符串

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

int main(void)
{
    char dest[20];
    char src[] = "JavaScript";

    // 将 src 复制到 dest 中
    memcpy(dest, src, strlen(src) + 1);
    puts(dest);

    return 0;
}

运行结果如下。

JavaScript

分析:

strlen(src) + 1 表示使用 strlen() 函数获取 src 的长度然后加上 1。之所以加上 1,其实是加上 '\0' 的长度。

示例 2:memcpy() 复制数组

#include <stdio.h>
#include <string.h>     // 或 #include <memory.h>

int main(void)
{
    int arr[] = {10, 20, 30, 40, 50};
    int resultArr[5];
    size_t elementsLength = sizeof(arr) / sizeof(arr[0]);   // 计算元素数量
    size_t bytesLength = sizeof(arr);                       // 计算总字节数

    // 使用 memcpy() 复制整个数组
    memcpy(resultArr, arr, bytesLength);

    printf("源数组: ");
    for (size_t i = 0; i < elementsLength; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    printf("目标数组: ");
    for (size_t i = 0; i < elementsLength; i++) {
        printf("%d ", resultArr[i]);
    }
    printf("\n");

    return 0;
}

运行结果如下。

源数组 : 10 20 30 40 50 
目标数组 : 10 20 30 40 50

分析:

在这个例子中,我们尝试使用 memcpy() 来复制一个数组。首先,我们使用 sizeof(arr) 计算了源数组的总字节数,然后将这些字节从 arr 复制到 resultArr。使用 memcpy() 不需要关心数据类型,它只会按照指定的字节数进行复制。

示例 3:memcpy() 复制结构体

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

// 定义结构体
struct Point 
{
    int x;
    int y;
};

int main(void)
{
    struct Point p1 = {10, 20};
    struct Point p2;

    // 使用 memcpy() 复制结构体
    memcpy(&p2, &p1, sizeof(struct Point));

    printf("源结构体: (%d, %d)\n", p1.x, p1.y);
    printf("目标结构体: (%d, %d)\n", p2.x, p2.y);

    return 0;
}

运行结果如下。

源结构体 : (10, 20)
目标结构体 : (10, 20)

分析:

memcpy() 也可以用来复制结构体,它会复制结构体占用的所有字节。需要注意的是,如果结构体中包含指针,则 memcpy() 复制的是指针本身的值(地址),而不是指针指向的数据。

memcpy() 与 strcpy() 的区别

memcpy() 和 strcpy() 都可以用于复制数据,但它们之间存在一个关键区别:

  • strcpy():用于复制 “字符串” 。它会从源字符串的开头一直复制到遇到终止符 '\0' 为止,并将终止符 '\0' 也复制到目标位置。strcpy() 不会关心复制了多少字节,它只依赖于终止符来确定复制结束。不过 strcpy() 存在缓冲区溢出风险,因为它不检查目标缓冲区大小。
  • memcpy():用于复制 “任意字节块” 。它会精确地复制指定的 n 个字节,而不关心是否遇到终止符 '\0'。memcpy() 适合用于复制非字符串数据(如数组、结构体)或字符串的一部分,而无需考虑终止符 '\0'。

用简单的一句话来说就是:strcpy() 是面向字符串的,而 memcpy() 是面向内存块的

memcpy() 与 memmove() 的区别

memcpy() 和 memmove() 都可以用于复制字节块,但它们在处理 “重叠内存区域” 时的行为是不同的。

  • memcpy():它的行为在 “源内存区域” 和 “目标内存区域” 重叠时是未定义的。在内存重叠的情况下使用 memcpy(),可能会导致数据被错误地复制,因为目标区域在复制过程中可能覆盖尚未读取的源区域数据。
  • memmove():它被设计用来正确处理 “源内存区域” 和 “目标内存区域” 重叠的情况。memmove() 会确保在将数据复制到目标区域之前,先将源区域的数据完全读取或暂存起来,从而避免数据损坏。其中,memmove() 在处理重叠区域时可能比 memcpy() 效率稍低。

如果能够确定 “源内存区域” 和 “目标内存区域” 不重叠,我们可以考虑使用 memcpy(),因为它的效率更高。如果 “源内存区域” 和 “目标内存区域” 可能存在重叠,或者不确定是否重叠,则我们应该始终使用更安全的 memmove() 函数。

上一篇: strcspn()

下一篇: memmove()

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号