当前位置: 首页 > news >正文

收集飞花令碎片——C语言内存函数 - 实践

收集飞花令碎片——C语言内存函数 - 实践

在这里插入图片描述
“山在雾中若隐若现,水在光里缓缓流淌。
我撑一叶小舟,不问归期,
只想听这天地的一声叹息。”

C语言 中,所谓的内存函数(Memory Functions),是指用于直接操作内存内容的一组标准库函数,主要定义在头文件:

#include <string.h>

这些函数通常以mem开头,主要作用是:
在内存中复制、比较、设置或移动一段字节数据
它们操作的单位是字节(byte),而不是字符或字符串

各函数详解

  • 1️⃣ memcpy(void *dest, const void *src, size_t n)
  • 2️⃣ memmove(void *dest, const void *src, size_t n)
  • 3️⃣ memset(void *ptr, int value, size_t n)
  • 4️⃣ memcmp(const void *a, const void *b, size_t n)
  • 5️⃣ memchr(const void *ptr, int value, size_t n)
  • 两内存函数的模拟实现
    • memcpy
      • 为何memcpy不处理内存重叠情况
    • memmove
  • 如果你觉得对你有帮助
  • 请给我一个三连哦谢谢啦

1️⃣ memcpy(void *dest, const void *src, size_t n)

  • 作用: 从源内存区域复制n个字节到目标区域。
  • 注意: 源和目标区域不能重叠!
char src[] = "Hello";
char dest[10];
memcpy(dest, src, 6);   // 复制包括'\0'在内的6个字节
printf("%s\n", dest);   // 输出 Hello

空间卷轴:memcpy函数



2️⃣ memmove(void *dest, const void *src, size_t n)

  • 作用: 与 memcpy 类似,但支持重叠区域。
char data[] = "12345";
memmove(data + 2, data, 3);   // 支持重叠
printf("%s\n", data);         // 输出 12123

空间卷轴:memmove函数



3️⃣ memset(void *ptr, int value, size_t n)

  • 作用: 将从 ptr 开始的 n 个字节都设为 value(按字节存)。
char buf[10];
memset(buf, 'A', 5);
buf[5] = '\0';
printf("%s\n", buf); // 输出 AAAAA

www空间卷轴:memset



4️⃣ memcmp(const void *a, const void *b, size_t n)

  • 作用: 比较两块内存前 n 个字节。

  • 返回值:

    • < 0 :a < b
    • = 0 :a == b
    • > 0 :a > b
char a[] = "abc";
char b[] = "abd";
int result = memcmp(a, b, 3);
printf("%d\n", result);  // 输出负数

空间卷轴:memcmp函数



5️⃣ memchr(const void *ptr, int value, size_t n)

  • 作用: 在内存中查找值为 value 的字节,返回首次出现位置的指针。
char str[] = "OpenAI";
char *p = memchr(str, 'A', 6);
if (p)
printf("Found at: %s\n", p); // 输出 AI

空间卷轴:memchr函数



两内存函数的模拟实现

memcpy

/**
* 内存复制函数
* 将指定字节数的数据从源内存地址复制到目标内存地址
*
* @param dst  目标内存地址(复制目的地)
* @param src  源内存地址(复制来源)
* @param count 要复制的字节数
* @return 返回目标内存地址的原指针
*/
void *memcpy(void *dst, const void *src, size_t count)
{
// 保存原始目标指针,用于函数返回
void *ret = dst;
// 参数有效性检查:确保目标地址和源地址都不为空
assert(dst != NULL);
assert(src != NULL);
/*
* 从低地址到高地址逐字节复制
* 注意:此实现不处理内存重叠情况
*/
while (count--) {
// 逐字节复制:将源地址的一个字节复制到目标地址
*(char *)dst = *(char *)src;
// 移动目标指针到下一个字节位置
dst = (char *)dst + 1;
// 移动源指针到下一个字节位置  
src = (char *)src + 1;
}
// 返回原始的目标指针(标准memcpy函数的约定)
return ret;
}

为何memcpy不处理内存重叠情况

memcpy(data + 2, data, 5);
// 源: data[0] 开始的5个字节 "abcde"
// 目标: data[2] 开始的5个字节
初始: a b c d e f g h i \0
步骤: a b a d e f g h i \0  (复制data[0]到data[2])a b a b e f g h i \0  (复制data[1]到data[3])a b a b a f g h i \0  (复制data[2]到data[4])a b a b a b g h i \0  (复制data[3]到data[5])a b a b a b a h i \0  (复制data[4]到data[6])
结果: "abababa hi"
  • 关键问题:
    第3步:data[4] = data[2],但此时 data[2] 已经被改为 a(不是原来的 c
    源数据在复制过程中被修改了!
// 循环展开 - 逐字节复制
*(data+2) = *(data+0);  // data[2] = 'a' → "abade fghi"
*(data+3) = *(data+1);  // data[3] = 'b' → "ababe fghi"  
*(data+4) = *(data+2);  // data[4] = 'a' → "ababa fghi"  ← 问题出现!
*(data+5) = *(data+3);  // data[5] = 'b' → "abababghi"
*(data+6) = *(data+4);  // data[6] = 'a' → "abababa hi"


memmove

/**
* 安全的内存移动函数
* 处理内存重叠情况,保证复制结果的正确性
*
* @param dst 目标内存地址
* @param src 源内存地址
* @param count 要复制的字节数
* @return 返回目标内存地址
*/
void *memmove(void *dst, const void *src, size_t count)
{
// 保存原始目标指针用于返回
void *ret = dst;
// 检查是否不需要重叠处理的情况:
// 1. 目标地址 <= 源地址 (反向重叠或不重叠)
// 2. 目标地址 >= 源地址 + count (完全不重叠)
if (dst <= src || (char *)dst >= ((char *)src + count)) {/** 非重叠缓冲区 或 反向重叠* 从低地址到高地址复制(正向复制)** 内存布局示例:* 情况1: dst <= src (反向重叠)*   [dst...dst+count]*          [src...src+count]** 情况2: dst >= src+count (不重叠)*   [src...src+count]    [dst...dst+count]*/while (count--) {// 逐字节复制:源数据 → 目标位置*(char *)dst = *(char *)src;// 指针向前移动一个字节dst = (char *)dst + 1;src = (char *)src + 1;}}else {/** 重叠缓冲区(正向重叠)* 从高地址到低地址复制(反向复制)** 内存布局示例:*   [src.........src+count]*        [dst.........dst+count]** 必须反向复制以避免覆盖尚未复制的源数据*/// 将指针移动到各自内存块的末尾dst = (char *)dst + count - 1;src = (char *)src + count - 1;// 从后往前逐字节复制while (count--) {// 逐字节复制:从末尾开始向开头复制*(char *)dst = *(char *)src;// 指针向后移动一个字节dst = (char *)dst - 1;src = (char *)src - 1;}}// 返回原始的目标指针return ret;}


如果你觉得对你有帮助

请给我一个三连哦谢谢啦

在这里插入图片描述

http://www.jsqmd.com/news/46748/

相关文章:

  • 绍兴一对一课外辅导机构推荐:2025年综合适配度排行榜
  • 绍兴一对一家教辅导机构推荐:2025权威测评排行榜,第一个性价比最高
  • 天门一对一家教机构终极推荐:2026最新辅导机构口碑TOP榜单!真实反馈闭眼选
  • 计算机视觉:YOLO实现目标识别+目标跟踪技术 pyqt界面 OpenCV 计算机视觉 深度学习 计算机(建议收藏)✅ - 指南
  • 2025 年电线电缆厂家 TOP 企业品牌推荐排行榜11月更新:消防 / 耐火 / 防火/ 阻燃 / 阻燃B1级 / 矿物质防火/ 柔性防火 / 低烟无卤火电缆电线推荐!
  • 潜江一对一课外辅导机构推荐,2026最新家教机构排行榜:靠谱不踩坑指南
  • Python的类对象、实例对象、类属性、实例属性、类方法、实例方法
  • 潜江一对一课外补习机构推荐:2026 最新教育机构天花板榜单!提分快还省钱
  • 2026年池州一对一家教机构推荐:五大辅导机构测评排行榜,综合实力全解析!
  • UVA1437 String painter 分析
  • Ubuntu22.04.4安装配置CUDA12.5,Cdnn官方详细版本
  • 2025 年 11 月电缆生产厂家排名出炉!知名品牌推荐 + 天津消防电缆厂家优选指南
  • 2025恩施一对一家教机构综合推荐,提分优选:靠谱方案推荐排行榜
  • 低门槛 + 全周期赋能:天翼云息壤大模型应用服务平台加速千行百业 AI 落地
  • 三层C/S架构的部署图
  • SATA接口调试问题记录
  • 3、步进电机梯形加减速
  • 云鼎未来,智营全局——哲讯科技以SAP Business ByDesign引领中型企业迈向协同运营新纪元
  • 2025 最新除甲醛机构权威推荐榜单:标杆企业技术服务测评解析,新房 / 家具 / 车内 / 办公除醛优选酒店除甲醛 / 室内除甲醛 / 附近除甲醛 / 学校除甲醛公司推荐
  • 超微Supermicro服务器安装英伟达A100,cuda
  • 镜头分辨率如何匹配工业相机的分辨率
  • linux,centos,aarch架构下载并部署redis
  • 2025年11月河南自习室加盟市场分析与品牌推荐
  • 习题解析之:判断火车票座位
  • 题解:NFLSOI#P10008. Speike和Tom
  • 洛谷 B4410:[GESP202509 一级] 金字塔 ← 循环结构
  • CF246E bfs 序上莫队
  • 2025 年 11 月降本增效管理咨询公司推荐排行榜,降本增效咨询,企业降本增效,提质增效咨询机构,专业实力与客户满意度深度解析
  • 小型食品厂省心了!CLC-S22R 控温又省成本​
  • 质量基石:读懂检查表,用好数字化管理利器