ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C语言的内存函数

C语言的内存函数 1. 引言在 C 语言编程中字符串处理函数如strcpy、strcmp虽然常用但它们只能处理以\0结尾的字符串数据。当我们需要操作内存块——比如结构体、数组、整数缓冲区等非字符串数据时就需要用到一组更底层的工具内存函数。内存函数直接操作原始内存字节不关心数据类型也不依赖\0结束符。它们是嵌入式开发、网络编程、底层系统实现中不可或缺的基础能力。本文将系统讲解 C 语言四大核心内存函数memcpy、memmove、memset、memcmp从函数原型、用法示例到底层模拟实现帮助你彻底掌握它们。2. 内存函数概览C 语言标准库string.h中提供了一组直接操作内存块的函数它们与字符串函数的本质区别在于按字节数操作而非按字符串长度操作。函数功能返回值memcpy复制内存块目标地址memmove移动内存块处理重叠目标地址memset填充内存块目标地址memcmp比较两个内存块整数0、0、0这四大函数构成了 C 语言内存操作的基础。下面逐一深入讲解。3. memcpy内存复制3.1 函数原型void*memcpy(void*dest,constvoid*src,size_tn);参数说明dest目标内存地址src源内存地址n要复制的字节数返回值返回dest的指针。3.2 功能说明memcpy从src指向的地址开始复制n个字节到dest指向的地址。它不关心数据类型可以复制任意内存内容。3.3 使用示例#includestdio.h#includestring.hintmain(){intsrc[5]{1,2,3,4,5};intdest[5]{0};// 复制 5 个 int共 20 字节memcpy(dest,src,sizeof(src));for(inti0;i5;i){printf(%d ,dest[i]);}printf(\n);return0;}输出1 2 3 4 53.4 注意事项memcpy不处理内存重叠。如果dest和src指向的区域有重叠行为是未定义的undefined behavior。复制的是原始字节不检查\0。参数n通常用sizeof()计算避免写死字节数。4. memmove安全的内存移动4.1 函数原型void*memmove(void*dest,constvoid*src,size_tn);4.2 与 memcpy 的区别memmove与memcpy功能几乎相同但memmove能安全处理源和目标内存重叠的情况。当内存区域重叠时memmove会先判断复制方向确保数据不被覆盖破坏。4.3 使用示例#includestdio.h#includestring.hintmain(){charstr[]Hello, World!;// 将字符串从下标 0 移到下标 7重叠移动memmove(str7,str,6);printf(%s\n,str);return0;}输出Hello, Hello!4.4 重叠场景对比#includestdio.h#includestring.hintmain(){charbuf1[20]abcdefghij;charbuf2[20]abcdefghij;// memcpy 处理重叠行为未定义memcpy(buf12,buf1,5);// memmove 处理重叠安全memmove(buf22,buf2,5);printf(memcpy 结果: %s\n,buf1);printf(memmove 结果: %s\n,buf2);return0;}建议当不确定是否重叠时优先使用memmove。5. memset内存填充5.1 函数原型void*memset(void*s,intc,size_tn);参数说明s目标内存起始地址c要填充的值以unsigned char转换后填充n填充的字节数5.2 功能说明memset将s指向的内存块的前n个字节都设置为值c。最常用于数组或结构体的初始化清零。5.3 使用示例#includestdio.h#includestring.hintmain(){intarr[10];// 将数组全部清零memset(arr,0,sizeof(arr));for(inti0;i10;i){printf(%d ,arr[i]);}printf(\n);return0;}输出0 0 0 0 0 0 0 0 0 05.4 结构体清零#includestdio.h#includestring.htypedefstruct{charname[20];intage;doublescore;}Student;intmain(){Student stu;// 结构体清零memset(stu,0,sizeof(stu));printf(name: %s\n,stu.name);printf(age: %d\n,stu.age);printf(score: %.2f\n,stu.score);return0;}输出name: age: 0 score: 0.005.5 注意事项memset按字节填充。对于int数组memset(arr, 1, sizeof(arr))并不会把每个int设为 1而是每个字节都变成0x01结果每个int是0x01010101。清零操作推荐使用0这是最安全、最常用的值。6. memcmp内存比较6.1 函数原型intmemcmp(constvoid*s1,constvoid*s2,size_tn);6.2 功能说明memcmp逐字节比较s1和s2指向的内存块的前n个字节。返回值返回值 0s1小于s2返回值 0两者相等返回值 0s1大于s26.3 使用示例#includestdio.h#includestring.hintmain(){inta[3]{1,2,3};intb[3]{1,2,3};intc[3]{1,2,4};// 比较前 3 个 int12 字节intresult1memcmp(a,b,sizeof(a));intresult2memcmp(a,c,sizeof(a));printf(a vs b: %d\n,result1);printf(a vs c: %d\n,result2);return0;}输出a vs b: 0 a vs c: -16.4 与 strcmp 的区别对比项strcmpmemcmp比较长度遇到\0停止固定比较n个字节适用数据字符串任意内存块是否检查\0是否7. 底层模拟实现理解内存函数的底层原理有助于写出更健壮的代码。下面给出四个函数的简化模拟实现。7.1 模拟 memcpyvoid*my_memcpy(void*dest,constvoid*src,size_tn){char*d(char*)dest;constchar*s(constchar*)src;for(size_ti0;in;i){d[i]s[i];}returndest;}7.2 模拟 memmovevoid*my_memmove(void*dest,constvoid*src,size_tn){char*d(char*)dest;constchar*s(constchar*)src;if(ds){// 从前向后复制for(size_ti0;in;i){d[i]s[i];}}elseif(ds){// 从后向前复制避免覆盖for(size_tin;i0;i--){d[i-1]s[i-1];}}returndest;}7.3 模拟 memsetvoid*my_memset(void*s,intc,size_tn){char*p(char*)s;unsignedcharvalue(unsignedchar)c;for(size_ti0;in;i){p[i]value;}returns;}7.4 模拟 memcmpintmy_memcmp(constvoid*s1,constvoid*s2,size_tn){constunsignedchar*p1(constunsignedchar*)s1;constunsignedchar*p2(constunsignedchar*)s2;for(size_ti0;in;i){if(p1[i]!p2[i]){returnp1[i]-p2[i];}}return0;}8. 常见应用场景8.1 数组复制doubledata1[100],data2[100];memcpy(data2,data1,sizeof(data1));8.2 结构体复制typedefstruct{intid;charname[32];}User;User u1{1,Alice};User u2;memcpy(u2,u1,sizeof(User));8.3 缓冲区清零charbuffer[1024];memset(buffer,0,sizeof(buffer));8.4 数据包比较unsignedcharpacket1[64],packet2[64];if(memcmp(packet1,packet2,64)0){printf(两个数据包内容相同\n);}9. 总结函数核心用途关键注意点memcpy复制内存块不处理重叠区域memmove移动内存块安全处理重叠区域memset按字节填充注意按字节填充的特性memcmp比较内存块固定字节数比较核心要点回顾内存函数按字节数操作不依赖\0结束符。内存重叠时优先使用memmove。memset按字节填充清零用0最安全。memcmp适合比较任意内存块包括含\0的二进制数据。理解底层模拟实现能帮助你更深刻地掌握这些函数的原理与边界。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进