C 库函数– memcpy() 

C 库函数 memcpy() 中文讲解(2025年)

memcpy() 是 C 标准库 <string.h> 中的函数,用于将一块内存的数据复制到另一块内存区域,广泛应用于数据处理、缓冲区操作和嵌入式系统。相比其他内存操作函数(如 strcpy),memcpy() 更通用,适用于任意数据类型(不仅仅是字符串),性能高效。本教程详细讲解 memcpy() 的语法、用法和实践,基于 C 标准文档、CSDN 和 C 社区,适合初学者和开发者。建议用 C 编译器(如 GCC、Clang)或在线 IDE(如 repl.it)练习。


一、memcpy() 概览(必知)

  • 功能:从源内存地址复制指定字节数的数据到目标内存地址。
  • 头文件<string.h>
  • 用途
  • 复制数组、结构体或任意数据块。
  • 初始化缓冲区或传递数据。
  • 在嵌入式系统中处理硬件寄存器或数据包。
  • 特点
  • 通用性:不限于字符串,适用于任何数据类型。
  • 高效:直接复制内存,性能优于逐元素赋值。
  • 无重叠限制:源和目标内存不能重叠(否则用 memmove())。
  • 2025年趋势
  • memcpy() 在嵌入式开发(如 IoT、RTOS)中仍是核心函数。
  • 在跨平台开发(如 KMP)中,C 模块用 memcpy() 处理 native 数据。
  • 现代编译器(如 GCC 14、Clang)优化 memcpy() 的 SIMD 指令。

二、核心语法与用法(必会)

1. 函数原型
void *memcpy(void *dest, const void *src, size_t n);
  • 参数
  • dest:目标内存地址(复制到的位置)。
  • src:源内存地址(复制来源)。
  • n:复制的字节数。
  • 返回值
  • 返回 dest 指针(目标地址)。
  • 无错误状态返回,需自行确保参数有效。
2. 基本用法
  • 复制数组
  #include <stdio.h>
  #include <string.h>

  int main() {
      int src[] = {1, 2, 3, 4, 5};
      int dest[5];
      memcpy(dest, src, sizeof(int) * 5);
      for (int i = 0; i < 5; i++) {
          printf("%d ", dest[i]); // 输出:1 2 3 4 5
      }
      return 0;
  }
  • 说明
  • sizeof(int) * 5 计算总字节数,确保复制整个数组。
  • destsrc 必须有足够空间。
  • 复制结构体
  #include <stdio.h>
  #include <string.h>

  struct Point {
      int x, y;
  };

  int main() {
      struct Point src = {10, 20};
      struct Point dest;
      memcpy(&dest, &src, sizeof(struct Point));
      printf("Dest: x=%d, y=%d\n", dest.x, dest.y); // 输出:x=10, y=20
      return 0;
  }
3. 复制字符串
  • strcpy 对比
  #include <stdio.h>
  #include <string.h>

  int main() {
      const char *src = "Hello";
      char dest[10];
      memcpy(dest, src, strlen(src) + 1); // 包含 \0
      printf("%s\n", dest); // 输出:Hello
      return 0;
  }
  • 说明
  • memcpy() 复制包括 \0 的字符串,类似 strcpy
  • memcpy() 不检查 \0,更适合已知长度的情况。
4. 注意内存重叠
  • 问题memcpy() 不处理源和目标内存重叠,可能导致未定义行为。
  • 解决方案:用 memmove() 替代:
  #include <stdio.h>
  #include <string.h>

  int main() {
      char str[] = "HelloWorld";
      memcpy(str + 2, str, 5); // 未定义行为(重叠)
      printf("%s\n", str); // 结果不可预测
      return 0;
  }

memmove()

  memmove(str + 2, str, 5); // 正确处理重叠

三、实践示例(综合应用)

  1. 缓冲区复制
#include <stdio.h>
#include <string.h>

int main() {
    char buffer[100] = "Data:12345";
    char backup[100];
    memcpy(backup, buffer, strlen(buffer) + 1);
    printf("Backup: %s\n", backup); // 输出:Data:12345

    // 修改原始缓冲区
    buffer[5] = '*';
    printf("Original: %s\n", buffer); // 输出:Data:*2345
    printf("Backup: %s\n", backup); // 输出:Data:12345
    return 0;
}


功能:复制缓冲区,保持备份独立。

  1. 嵌入式数据处理(KMP 示例)
#include <stdio.h>
#include <string.h>

struct Packet {
    int id;
    char data[20];
};

extern "C" {
    // 假设与 Kotlin 互操作
    void copyPacket(struct Packet *dest, struct Packet *src) {
        memcpy(dest, src, sizeof(struct Packet));
    }
}

int main() {
    struct Packet src = {1, "SensorData"};
    struct Packet dest;
    copyPacket(&dest, &src);
    printf("Dest: id=%d, data=%s\n", dest.id, dest.data); // 输出:id=1, data=SensorData
    return 0;
}


功能:复制数据包,模拟嵌入式系统或 KMP native 模块。


四、注意事项与最佳实践

  1. 内存安全
  • 确保 dest 有足够空间(至少 n 字节)。
  • 检查指针非空:
    c if (dest && src) memcpy(dest, src, n);
  1. 内存重叠
  • 源和目标重叠时,用 memmove()
    c memmove(dest, src, n); // 安全处理重叠
  1. 性能优化
  • memcpy() 适合大块数据复制,优于循环赋值:
    c // 慢 for (int i = 0; i < n; i++) dest[i] = src[i]; // 快 memcpy(dest, src, n);
  • 现代编译器可能内联 memcpy(),利用 SIMD 指令。
  1. 跨平台兼容
  • memcpy() 是 C 标准函数,跨平台可靠。
  • 在 KMP 项目中,C 模块用 memcpy() 与 Kotlin 互操作:
    kotlin @CName("copyPacket") fun copyPacket(dest: CPointer<Packet>, src: CPointer<Packet>)
  1. 2025年趋势
  • 嵌入式开发memcpy() 用于高效数据传输(如 DMA 缓冲区)。
  • 安全性:结合 bounds-checking 工具(如 AddressSanitizer)检测溢出:
    bash gcc -fsanitize=address program.c

五、学习建议

  • 练习:用 GCC 实践 memcpy() 复制数组、结构体,比较与循环赋值的性能。
  • 资源
  • C 标准文档:https://en.cppreference.com/w/c/string/byte/memcpy
  • CSDN:搜索“C memcpy”。
  • B站:C 语言教程(如“尚硅谷 C”)。
  • 时间:1-2 小时掌握 memcpy(),1 天熟悉内存操作。
  • 实践:实现缓冲区复制或数据包处理程序。

六、总结

C 库函数 memcpy() 必知内存复制、高效性和通用性,必会复制数组/结构体和避免内存重叠。2025年,memcpy() 仍是 C/C++ 内存操作核心,适合嵌入式和 KMP 开发。相比循环赋值,memcpy() 高效但需注意安全。

如果需要具体场景代码(如嵌入式示例或 KMP 集成)或有问题,告诉我,我可以提供更详细解答!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注