memcpy 函数 —— 内存拷贝的 “高效搬运工”
memcpy是 “按字节精准拷贝的内存搬运神器”,核心优势是高效、简洁、跨类型通用,专门解决 “批量二进制数据复制” 需求~
·
在 C/C++ 编程中,内存数据的批量复制是高频操作,而 memcpy 函数就是标准库(藏在 <string.h> 头文件里)中专门解决这类需求的 “高效搬运工”!核心技能是:把一块连续内存空间里的二进制数据,原封不动地批量拷贝到另一块连续内存,全程按字节精准搬运,不丢数据、不乱顺序~
一、memcpy 到底是个啥?🤔
关键特征速览,一眼摸清核心:
- 操作逻辑:按字节逐位拷贝(不管源数据是 int 数组、结构体、字符串还是堆内存块,都以 1 字节为单位完整复制);
- 函数原型:
void *memcpy(void *dest, const void *src, size_t num)(参数含义:目标内存地址dest、源内存地址src、拷贝的总字节数num); - 核心优势:无类型限制(通过
void *适配所有数据类型)、拷贝精准(二进制原封不动复制)、效率拉满(库函数优化,比手动循环快得多); - 小提醒:
src地址加const保护,避免拷贝时意外修改源数据;dest和src内存区域尽量不重叠(重叠建议用memmove)。
二、为啥非要用 memcpy?🧐 手动循环拷贝不香吗?
还真不香!memcpy 的存在就是为了踩碎手动拷贝的 “坑”,优势直接拉满:
- 告别 “循环冗余”🚫:想拷贝 1000 个 int 元素的数组?手动写 for 循环又长又容易出错,
memcpy一行搞定,代码极简; - 效率碾压手动拷贝⚡:
memcpy是编译器优化过的底层实现(部分场景用汇编指令加速),比手动循环拷贝快一个量级,大数据量下差距更明显; - 跨类型 “通吃”🌍:不管是拷贝 int 数组、char 字符串、自定义结构体,还是堆内存块,
memcpy都能直接适配,不用为不同类型写重复拷贝逻辑; - 拷贝精准无误差✅:二进制级别的逐字节复制,能完整保留源数据的所有细节(包括结构体里的填充字节、二进制位模式),不会出现手动赋值遗漏或类型转换错误。
三、memcpy 的 “神仙用法”✨ 编程中常用到爆!
memcpy 的核心是 “批量精准拷贝”,这 4 个场景堪称 “刚需用法”,学会直接提升编程效率:
- 数组批量复制📊:把一个数组的全部或部分元素快速拷贝到另一个数组,避免逐个赋值的繁琐;
- 结构体深拷贝📦:自定义结构体(无指针成员时)直接整体拷贝,不用逐个成员赋值,防止遗漏;
- 堆内存数据迁移🗄️:
malloc分配新堆内存后,把旧内存的数据完整迁移过去,或在堆内存块之间传递数据; - 缓冲区数据传递📡:网络编程、文件操作中,把缓冲区的二进制数据(如协议包、文件字节流)快速拷贝到目标内存,保证数据完整性。
四、实用示例 🚀 直接抄作业!
示例 1:数组批量拷贝(告别逐个赋值)
#include <string.h>
#include <stdio.h>
int main() {
int src_arr[5] = {1, 2, 3, 4, 5};
int dest_arr[5]; // 未初始化的目标数组
// 拷贝整个源数组,sizeof自动计算总字节数(5*4=20字节)
memcpy(dest_arr, src_arr, sizeof(src_arr));
printf("目标数组:");
for (int i = 0; i < 5; i++) {
printf("%d ", dest_arr[i]); // 输出:1 2 3 4 5 🎉 完全复刻源数组!
}
return 0;
}
示例 2:结构体整体拷贝(不怕漏成员)
#include <string.h>
#include <stdio.h>
// 定义学生结构体
typedef struct {
int id;
char name[20];
float score;
} Student;
int main() {
Student s1 = {101, "Zhang San", 95.5};
Student s2; // 空结构体
// 直接拷贝整个结构体,所有成员一次性复制
memcpy(&s2, &s1, sizeof(Student));
printf("拷贝后的结构体:id: %d, name: %s, score: %.2f",
s2.id, s2.name, s2.score);
// 输出:id: 101, name: Zhang San, score: 95.50 📚 成员无遗漏!
return 0;
}
示例 3:堆内存数据迁移(安全传递数据)
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
// 源堆内存:分配5个int(20字节)并初始化
int *src_heap = (int*)malloc(5 * sizeof(int));
for (int i = 0; i < 5; i++) {
src_heap[i] = i + 10; // 源数据:10,11,12,13,14
}
// 目标堆内存:分配同样大小的空间
int *dest_heap = (int*)malloc(5 * sizeof(int));
if (src_heap != NULL && dest_heap != NULL) {
memcpy(dest_heap, src_heap, 5 * sizeof(int)); // 拷贝堆内存数据
// 验证拷贝结果
printf("目标堆内存数据:");
for (int i = 0; i < 5; i++) {
printf("%d ", dest_heap[i]); // 输出:10 11 12 13 14 🗄️
}
// 释放内存,避免内存泄漏
free(src_heap);
free(dest_heap);
src_heap = NULL;
dest_heap = NULL;
}
return 0;
}
示例 4:缓冲区部分拷贝(精准截取数据)
#include <string.h>
#include <stdio.h>
int main() {
// 源缓冲区:模拟网络接收的二进制数据
unsigned char src_buf[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};
unsigned char dest_buf[5]; // 目标缓冲区:只存前5个字节
// 拷贝源缓冲区前5个字节到目标缓冲区
memcpy(dest_buf, src_buf, 5);
printf("目标缓冲区数据:");
for (int i = 0; i < 5; i++) {
printf("0x%02X ", dest_buf[i]); // 输出:0x01 0x02 0x03 0x04 0x05 ⚙️
}
return 0;
}
五、总结 📌 一句话拿捏 memcpy!
memcpy 是 “按字节精准拷贝的内存搬运神器”,核心优势是高效、简洁、跨类型通用,专门解决 “批量二进制数据复制” 需求~
必记要点:
num是拷贝的「总字节数」,必须用sizeof或 “元素数 × 类型大小” 计算(比如 int 数组拷贝 5 个元素,要传5×4而不是 5,否则拷贝不完整);- 目标内存
dest必须有足够空间(至少能容纳num字节),否则会造成内存越界崩溃; - 避免
dest和src内存区域重叠(比如把数组前 3 个元素拷贝到后 3 个位置),重叠场景用memmove更安全; - 不能拷贝字符串常量(如
"hello")到只读内存,也不能修改源数据的只读属性(src加const就是为了提醒)。
适用边界:
适合数组、结构体、堆内存、缓冲区等 “连续内存块” 的批量拷贝;如果是字符串拷贝(需要自动识别 \0 结束符),可以用 strcpy;如果是重叠内存拷贝,优先用 memmove;如果是单个值填充,还是得找 memset 哦~
总之,只要涉及 “批量复制二进制数据”,直接喊 memcpy 就对了,编程效率直接翻倍,还能避免手动拷贝的各种坑!🚀
更多推荐




所有评论(0)