C语言 memcpy 的使用

memcpy 是 C 语言中非常重要的一个函数,用于内存块的复制 。它定义在标准头文件 <string.h> 中。


📌 函数原型

c 复制代码
void *memcpy(void *dest, const void *src, size_t n);

参数说明:

参数 类型 含义
dest void * 目标内存地址(要复制到哪里)
src const void * 源内存地址(从哪里复制)
n size_t 要复制的字节数

返回值:

  • 返回指向目标内存 dest 的指针(即第一个参数)。
  • 通常可以忽略返回值,但在链式调用或需要检查时有用。

✅ 使用步骤与要点

  1. 包含头文件

    c 复制代码
    #include <string.h>
  2. 确保目标空间足够大

    • dest 必须有足够的内存空间容纳 n 个字节,否则会导致缓冲区溢出和未定义行为。
  3. 避免内存重叠

    • 如果源和目标内存区域有重叠 ,使用 memcpy 会导致未定义行为
    • 此时应使用 memmove,它是安全处理重叠内存的版本。

💡 示例代码

示例 1:基本用法 ------ 复制数组

c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    int src[] = {10, 20, 30, 40, 50};
    int dest[5];

    // 复制 5 个整数(每个 int 通常是 4 字节,共 20 字节)
    memcpy(dest, src, sizeof(src));

    for (int i = 0; i < 5; i++) {
        printf("%d ", dest[i]);  // 输出: 10 20 30 40 50
    }

    return 0;
}

示例 2:复制结构体

c 复制代码
#include <stdio.h>
#include <string.h>

typedef struct {
    int id;
    char name[20];
    float score;
} Student;

int main() {
    Student s1 = {1001, "Alice", 95.5f};
    Student s2;

    memcpy(&s2, &s1, sizeof(Student));

    printf("ID: %d, Name: %s, Score: %.1f\n", 
           s2.id, s2.name, s2.score);
    // 输出: ID: 1001, Name: Alice, Score: 95.5

    return 0;
}

示例 3:复制字符串(非最佳实践)

c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, world!";
    char dest[50];

    memcpy(dest, src, strlen(src) + 1);  // +1 包含 '\0'

    printf("Copied string: %s\n", dest);

    return 0;
}

⚠️ 注意:对于字符串,推荐使用 strcpy 或更安全的 strncpy / strlcpy / snprintf


⚠️ 常见错误与陷阱

错误 说明
❌ 目标空间不足 char dest[10]; memcpy(dest, src, 100); → 写越界,崩溃或安全漏洞
❌ 源指针为空 memcpy(dest, NULL, n) → 崩溃
❌ 目标指针为空 memcpy(NULL, src, n) → 崩溃
❌ 内存重叠 memcpy(buf+1, buf, 10); → 未定义行为!应改用 memmove

✅ 正确做法示例(使用 memmove 处理重叠):

c 复制代码
char buf[] = "abcdef";
memmove(buf + 1, buf, 5);  // 将 "abcde" 左移一位
// 结果: "aabcde"

🔍 memcpy vs memmove

函数 是否支持内存重叠 性能 推荐场景
memcpy ❌ 不保证 更快 确定无重叠时使用
memmove ✅ 安全支持 稍慢 可能存在重叠时使用

建议 :如果不确定是否重叠,优先使用 memmove


🛠️ 技巧:复制部分数据

c 复制代码
double data[100];
double subset[10];

// 只复制前 10 个 double
memcpy(subset, data, 10 * sizeof(double));

✅ 安全使用建议

  1. 使用 sizeof() 计算大小,避免硬编码。
  2. 确保目标缓冲区已分配且足够大。
  3. 对于字符串操作,考虑使用更高层函数(如 strcpy, strncpy)。
  4. 避免跨线程共享未保护的内存拷贝。
  5. 在嵌入式或性能敏感场景中,memcpy 是高效选择。

🧪 小结:一句话记住 memcpy

"按字节复制一块内存,不管内容是什么。"

它不关心你复制的是 intfloat、结构体还是字符串 ------ 它只是把一串字节从一个地方搬到另一个地方。


如果你是在实现序列化、解析协议、操作二进制数据等底层任务,memcpy 是不可或缺的工具。但务必小心使用,防止内存错误!

相关推荐
迎風吹頭髮3 小时前
UNIX下C语言编程与实践9-UNIX 动态库创建实战:gcc 参数 -fpic、-shared 的作用与动态库生成步骤
c语言·数据库·unix
MediaTea4 小时前
Python IDE:Spyder
开发语言·ide·python
不枯石4 小时前
Matlab通过GUI实现点云的均值滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab·均值算法
不枯石5 小时前
Matlab通过GUI实现点云的双边(Bilateral)滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab
二十雨辰5 小时前
vite如何处理项目中的资源
开发语言·javascript
聆风吟º6 小时前
远程录制新体验:Bililive-go与cpolar的无缝协作
开发语言·后端·golang
想唱rap7 小时前
直接选择排序、堆排序、冒泡排序
c语言·数据结构·笔记·算法·新浪微博
豆浆whisky7 小时前
netpoll性能调优:Go网络编程的隐藏利器|Go语言进阶(8)
开发语言·网络·后端·golang·go
蓝天白云下遛狗7 小时前
go环境的安装
开发语言·后端·golang
CAir27 小时前
go协程的前世今生
开发语言·golang·协程