今天我们来聊聊 C 语言里那几个平时不太起眼但一用起来就能让你代码起飞或者翻车的家伙——内存函数。很多人学 C 语言字符串函数strcpy,strcat背得滚瓜烂熟但一碰到memcpy和memmove就开始犯迷糊“这不都是复制粘贴吗为啥要搞两个”兄弟这就好比你以为剪刀和菜刀都是切东西的切菜用哪个都行但你总不能用剪刀去剁排骨吧今天咱们就来扒一扒string.h里这四个“扫地僧”memcpy、memmove、memset、memcmp。看完这篇你就知道为啥有些 Bug 只有在半夜才会出现以及为啥大佬们写代码都喜欢直接怼内存。一、memcpy风风火火的“冒失鬼”搬运工它是干啥的memcpy的工作很简单不管三七二十一从源地址开始抄起num个字节原封不动地扔到目标地址。它有个最大的特点眼瞎。它不关心你内存里放的是整数、浮点数还是结构体甚至不关心里面有没有数据它的任务就是把那一堆 0101 搬过去。eg你有这么一串数字{1,2,3,4,5,...}你想把它复制到另一个空数组里复制 20 个字节也就是 5 个 int结果arr2里变成了{1,2,3,4,5,...}。没毛病致命弱点内存重叠这是memcpy最大的坑。假如你想把数组前 5 个数覆盖到第 3 个位置开始的地方预期{1,2,1,2,3,4,5,8,9,10}你写了注意了​ 虽然有时候你运行发现结果居然是对的但这叫“未定义行为”Undefined Behavior。这就好比你让一个人同时踩在两个凳子上他可能站得住也可能下一秒就摔死。编译器心情不好换了优化等级、换了平台的时候结果就可能炸了。口诀只要内存不重叠memcpy 是首选一旦重叠立马换人。二、memmove稳如老狗的“老司机”搬运工既然memcpy搞不定重叠那就轮到memmove出场了。它是干啥的memmove是memcpy的 Pro 版或者说防撞版。它专门处理内存重叠的情况。老司机是怎么开车的面对重叠memmove会先判断一下如果源地址在目标地址后面那就从头往后拷跟 memcpy 一样。如果源地址在目标地址前面就是上面那个坑爹情况老司机就会从后往前拷。为什么从后往前因为这样不会覆盖掉还没来得及拷贝的数据。还是刚才那个例子结果稳稳地输出1 2 1 2 3 4 5 8 9 10。人话总结memcpy是个愣头青memmove是个心细的老管家。平时能用memcpy就用因为它稍微快那么一丢丢但只要涉及自己拷贝自己或者地址有交叉闭眼选memmove。三、memset强迫症晚期的“粉刷匠”它是干啥的memset负责把一块内存区域的每一个字节都刷成同一个值。最容易踩的坑它是按“字节”刷的这一点太重要了memset不管你是int数组还是char数组它眼里只有“字节”。正确用法字符这里x正好是一个字节完美。经典翻车现场整数如果你想把一个int数组初始化为 1你以为数组里全是1实际上因为int占 4 个字节你刷完之后每个int变成了0x01010101也就是十进制的 16843009。避坑指南想清零memset(arr, 0, sizeof(arr));因为只有 0 不管怎么填都是 0。想初始化字符随便用。想初始化非 0 的整数老老实实写循环或者用calloc。四、memcmp拿着放大镜的“较真裁判”它是干啥的比较两个内存块的内容看看谁大谁小或者是不是一样。和 strcmp 有啥区别strcmp遇到\0就停了它是字符串专用。memcmp不管你有没有\0我只管比较你给我的num个字节。代码演示在这个例子里g103比G71大所以buffer1更大。应用场景非常适合比较结构体、二进制数据块或者像这里一样精确控制比较多少个字节不受字符串结束符影响。五、总结时间到啦事已至此先吃饭吧也整理整理这些小小知识点把这四个兄弟分清楚函数外号核心技能注意事项memcpy​冒失鬼快速拷贝内存严禁内存重叠否则结果看脸memmove​老司机安全拷贝内存允许内存重叠慢一点点但稳memset​粉刷匠批量填充字节除了 0别用它初始化int数组memcmp​裁判比较内存内容按字节比不怕\0可指定长度最后送大家一句忠告C 语言直接操作内存虽然爽但一定要清楚自己在干什么。毕竟指针满天飞的感觉虽然像黑客但 Segmentation fault段错误的感觉就像被扇了一耳光。