尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

C语言内存函数的使用

C语言内存函数的使用 序言为什么要学内存函数前面学的字符串函数如strcpy、strcmp只能操作字符串遇\0就停而内存函数操作的是字节能处理任意类型的数据——整型数组、浮点数组、结构体……统统搞定。对比维度字符串函数内存函数操作对象仅字符串任意类型结束条件遇\0停止按指定字节数头文件string.hstring.h1.memcpy— 内存拷贝1.1 函数原型void*memcpy(void*destination,constvoid*source,size_tnum);参数说明destination指向目标内存块的指针source指向源内存块的指针num要拷贝的字节数不是元素个数返回值目标地址destination功能从source复制num个字节到destination。前提 ⚠️source和destination不能重叠否则行为未定义此时应使用memmove。1.2 使用示例#includestdio.h#includestring.hintmain(){intarr1[]{1,2,3,4,5,6,7,8,9,10};intarr2[10]{0};memcpy(arr2,arr1,20);// 20 5个int × 4字节inti0;for(i0;i10;i){printf(%d ,arr2[i]);// 输出1 2 3 4 5 6 7 8 9 10}return0;}注意第三个参数是字节数不是元素个数。int占 4 字节拷贝 5 个int要写5 * sizeof(int)即20。1.3 模拟实现void*my_memcpy(void*dst,constvoid*src,size_tcount){void*retdst;assert(dst);assert(src);/* * 从低地址向高地址逐字节复制 */while(count--){*(char*)dst*(char*)src;dst(char*)dst1;src(char*)src1;}returnret;}核心思路将指针强转为char*实现逐字节复制实现不挑类型的通用拷贝。2.memmove— 安全内存拷贝支持重叠2.1 函数原型void*memmove(void*destination,constvoid*source,size_tnum);功能和memcpy一样但允许source和destination有重叠区域。内部会自动判断重叠方向选择合适的拷贝顺序保证数据安全。对比memcpymemmove重叠处理❌ 不支持未定义行为✅ 正确处理效率略高不需要判断略低有判断开销使用建议确定不重叠时使用不确定时优先使用2.2 使用示例重叠拷贝#includestdio.h#includestring.hintmain(){intarr1[]{1,2,3,4,5,6,7,8,9,10};memmove(arr12,arr1,20);// 把前5个元素向后偏移2个位置inti0;for(i0;i10;i){printf(%d ,arr1[i]);// 输出1 2 1 2 3 4 5 8 9 10}return0;}图解arr12指向第 3 个元素的地址索引 2。将{1,2,3,4,5}拷贝到{3,4,5,6,7}的位置产生重叠。结果前 7 个元素变成{1,2,1,2,3,4,5}后 3 个保持原样{8,9,10}。2.3 模拟实现void*my_memmove(void*dst,constvoid*src,size_tcount){void*retdst;if(dstsrc){/* * 情况一无重叠或 dst 在 src 之前 * 从低地址向高地址复制和 memcpy 一样 */while(count--){*(char*)dst*(char*)src;dst(char*)dst1;src(char*)src1;}}else{/* * 情况二dst 在 src 之后且存在重叠 * 从高地址向低地址复制 —— 避免覆盖尚未拷贝的源数据 */while(count--){//count进来后才变19指向最后一个字节*((char*)dstcount)*((char*)srccount);}}returnret;}核心逻辑dst ≤ src目标在源前面 → 从前往后拷没问题。dst ≥ src count目标在源后面但离得远、无交集 → 从前往后拷。其它情况重叠且 dst 在 src 之后必须从后往前拷否则会覆盖掉还没拷贝的数据3.memset— 内存设置3.1 函数原型void*memset(void*ptr,intvalue,size_tnum);参数说明ptr指向要设置的内存块的指针value要设置的值会被转为unsigned charnum要设置的字节数返回值ptr的地址功能将ptr指向的前num个字节每个字节都设置为值value。关键value会被强转为unsigned char所以是逐字节设置不是按元素类型设置。3.2 使用示例#includestdio.h#includestring.hintmain(){charstr[]hello world;memset(str,x,6);// 将前 6 个字节设为 xprintf(%s\n,str);// 输出xxxxxxworldreturn0;}// 常用场景将整型数组全部置零intarr[10];memset(arr,0,sizeof(arr));// 每个字节都设为 0 → 所有 int 都变成 0// ⚠️ 坑设置非零值要谨慎intarr[10];memset(arr,1,sizeof(arr));// 结果是每个字节 1 → 每个 int 0x01010101 16843009不是 1避坑memset逐字节设值。想把int数组全设为0或-10xFFFFFFFF是安全的设为其它值如1只对char数组有效对多字节类型会出错3.3 常用场景场景代码字符数组初始化memset(buf, 0, sizeof(buf));整型数组归零memset(arr, 0, sizeof(arr));结构体清零memset(stu, 0, sizeof(stu));设为特定字符memset(str, A, 10);4.memcmp— 内存比较4.1 函数原型intmemcmp(constvoid*ptr1,constvoid*ptr2,size_tnum);参数说明ptr1指向第一个内存块ptr2指向第二个内存块num要比较的字节数返回值返回值含义 0ptr1大于ptr2在第一个不同的字节处0两个内存块的前num个字节完全相同 0ptr1小于ptr2比较规则逐字节比较遇到第一对不相等的字节就出结果比较它们的 ASCII / 数值大小。4.2 使用示例#includestdio.h#includestring.hintmain(){charbuffer1[]DWgaOtP12df0;charbuffer2[]DWGAOTP12DF0;intn;nmemcmp(buffer1,buffer2,sizeof(buffer1));if(n0)printf(%s is greater than %s.\n,buffer1,buffer2);elseif(n0)printf(%s is less than %s.\n,buffer1,buffer2);elseprintf(%s is the same as %s.\n,buffer1,buffer2);// 输出DWgaOtP12df0 is greater than DWGAOTP12DF0.// 原因第3个字节 g(103) G(71)return0;}4.3memcmpvsstrcmp对比维度memcmpstrcmp比较终止比较完num个字节遇到\0就停止比较对象任意内存块仅字符串是否有\0要求不关心依赖\0结束四大内存函数全景速查表函数功能支持重叠关键注意点memcpy拷贝内存❌不能重叠第三个参数是字节数memmove安全拷贝✅不确定是否重叠时用它memset设置内存—逐字节设置非 0/-1 慎用于多字节类型memcmp比较内存—逐字节比较不关心\0内存分类记忆图内存操作函数string.h ├── 拷贝memcpy ──→ 不可重叠 │ memmove ──→ 可重叠更安全 ├── 设置memset ──→ 逐字节设值0 / -1 最安全 └── 比较memcmp ──→ 逐字节比较不管 \0总结维度要点与字符串函数的区别内存函数不关心\0按字节数操作可处理任意类型memcpy vs memmove不确定是否重叠 → 用memmove确定不重叠 → 用memcpymemset 避坑只能放心地设为0或-1对多字节类型其它值只对char安全memcmp和strcmp不同它不遇到\0就停而是老老实实比完num个字节第三个参数都是字节数不是元素个数别忘sizeof()⚡一句话总结memcpy高效拷贝不重叠memmove安全拷贝可重叠memset批量设值避坑 0/-1memcmp逐字节比较不管\0。四大内存函数C 语言操作数据的瑞士军刀
返回列表