mem系列函数学习总结

本文详细介绍了C/C++中的内存操作函数,包括memset用于填充内存、memcpy进行逐字节复制、memccpy带条件终止、以及带有安全限制的memcpy_s和memmove_s。还对比了memmove与memmove_s的区别,强调了在处理内存重叠时的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.memset

声明:

void *memset(
   void *dest,
   int c,
   size_t count 
);

参数:

dest:指向预设置的内存空间的指针;

c:拷贝进内存空间的值;

count:设置内存空间的字节数大小。

函数作用:

将指定大小的内存空间中的值均设置为c值。

返回值:

返回一个指向目标存储区dest的指针。

2.memcpy

声明:

 void *memcpy(
    void *dest,
    const void *src,
    size_t count
);

参数:

dest:指向存放复制内容的内存空间首地址的指针;

src:指向被复制内容的内存空间首地址的指针;

count:复制内容的最大字节数。

函数作用:

将src中的内容按字节挨个复制到dest中。

返回值:

返回一个指向目标存储区dest的指针。

3.memccpy

声明:

void *memccpy(
   void *dest, 
   void *src,
   unsigned char ch,
   unsigned int count
);

参数:

dest:指向存放复制内容的内存空间首地址的指针;

src:指向被复制内容的内存空间首地址的指针;

ch:停止字符,复制过程中str2遇到此字符后停止复制;

count:复制内容的最大字节数。

函数作用:

由src所指内存区域复制不多于count个字节到dest所指内存区域,如果遇到字符ch则停止复制。

返回值:

返回指向字符ch后的第一个字符的指针,如果src前count个字节中不存在ch则返回NULL。

4.memcpy_s

声明:

errno_t memcpy_s(
   void *dest,
   size_t numberOfElements,
   const void *src,
   size_t count 
);

参数:

dest:指向存放复制内容的内存空间首地址的指针;

numberOfElements:dest所指内存空间的缓冲区大小,实际复制的字节数上限;

src:指向被复制内容的内存空间首地址的指针;

count:复制内容的期望字节数大小。

函数作用:

由src所指内存区域复制不多于count个字节到dest所指内存区域,但是count不能大于numberOfElements。这样可以确保dest所指内存空间的数据安全。

返回值:

一个整型值(errno_t),用来判断复制是否完成。0表示成功。

5.memcmp

声明:

int memcmp(
   const void *buf1,
   const void *buf2,
   size_t count
);

参数:

buf1:指向欲比较的第一个缓冲区的指针;

buf2:指向欲比较的第二个缓冲区的指针;

count:比较的字节数大小。

函数作用:

按字节依次比较两个缓冲区的数据大小。

返回值:

一个整型:<0 表示按字节比较 buf1 < buf2;

                  =0 表示按字节比较 buf1 = buf2;

                  >0 表示按字节比较 buf1 > buf2

6.memchr

声明:

void *memchr(
   const void *buf,
   int c,
   size_t count
); // C only

void *memchr(
   void *buf,
   int c,
   size_t count
); // C++ only

const void *memchr(
   const void *buf,
   int c,
   size_t count
); // C++ only

参数:

buf:指向欲查找内容的缓冲区的指针;

c:欲查找的字符;

count:查找的字符数。

函数作用:

在一个缓冲区中查找指定大小区间里是否存在指定字符c。

返回值:

查找成功则返回指向c值的第一个指针,查找失败则返回NULL。

7.memmove

声明:

void *memmove(
   void *dest,
   const void *src,
   size_t count 
);

参数:

dest:指向存放复制内容的内存空间首地址的指针;

src:指向被复制内容的内存空间首地址的指针;

count:复制内容的最大字节数。

函数作用:

将src中的内容按字节挨个复制到dest中。

返回值:

返回一个指向目标存储区dest的指针。

*注意:memmove与memcpy的区别:

当复制的内存空间与被复制的内存空间发生局部重叠时,memmove可以保证拷贝内容正确并成功覆盖。另外在高级VS版本中,两者在内部实现上已经一致。

8.memmove_s

声明:

errno_t memmove_s(
   void *dest,
   size_t numberOfElements,
   const void *src,
   size_t count
);

参数:

dest:指向存放复制内容的内存空间首地址的指针;

numberOfElements:dest所指内存空间的缓冲区大小,实际复制的字节数上限;

src:指向被复制内容的内存空间首地址的指针;

count:复制内容的期望字节数大小。

函数作用:

由src所指内存区域复制不多于count个字节到dest所指内存区域,但是count不能大于numberOfElements。这样可以确保dest所指内存空间的数据安全。

返回值:

一个整型值(errno_t),用来判断复制是否完成。0表示成功。

*注意:memmove_s与memcpy_s的区别:

当复制的内存空间与被复制的内存空间发生局部重叠时,memmove_s可以保证拷贝内容正确并成功覆盖。另外在高级VS版本中,两者在内部实现上已经一致。

### C语言 `free` 函数的实现原理与源码分析 在C语言中,`free` 是标准库函数之一,用于释放之前由 `malloc` 或其他动态内存分配函数分配的内存。其主要功能是从堆中回收指定地址所指向的内存区域,并将其返回给操作系统或内存管理器以便后续重用。 #### 1. 堆内存管理基础 为了理解 `free` 的工作原理,需先了解堆内存的基本结构。当程序调用 `malloc` 分配一块内存时,实际分配的是一个更大的块,其中不仅包含了用户请求的部分,还可能附加了一些元数据(metadata)。这些元数据通常存储在每块内存前面的一个头部结构中,记录了该块大小以及其他状态信息[^3]。 #### 2. Free 的基本流程 以下是 `free` 函数的主要执行过程: - **验证指针合法性** 首先检查传入的指针是否有效。如果传递了一个非法或者未初始化的指针,则可能导致未定义行为。现代实现可能会加入额外的安全机制来检测错误使用的场景。 - **定位对应的内存块头信息** 使用指针减去偏移量找到对应内存块的真实起始位置及其关联的元数据部分。这一操作依赖于具体平台上的 malloc 实现细节。 - **更新链表/树状结构中的节点状态** 动态内存管理系统内部维护着一系列的数据结构用来跟踪哪些区域处于已占用还是可用的状态。Free 就是要把当前释放掉的空间重新插回到合适的空闲列表里边去。 - **合并相邻碎片 (Coalesce)** 如果被释放的这块紧挨着前后两侧也都是自由区的话,那么它们就会被连成一片形成一个新的更大范围的闲置区间;这样做的目的是减少因频繁申请释放而导致的小片断化现象发生概率从而提高整体性能表现水平[^3]。 #### 3. GNU glibc 中的具体实现剖析 以GNU libc为例,在其实现当中采用了多种策略和技术手段优化效率并兼顾兼容性和稳定性需求: - **Arena 和 Heap 结构设计** - Arena 表示独立的工作环境,默认情况下每个线程拥有自己的 arena 来避免竞争锁带来的开销问题。 - 而 heap 则代表整个进程可利用的所有虚拟地址空间资源集合体。 - **Fastbins 快速路径支持** - 对小于一定阈值的对象采用 fastbin 方式快速处理,省去了复杂的查找比较环节加快速度。 - **Sbrk vs Mmap 混合模式切换逻辑判断条件设定合理与否直接影响到最终效果的好坏程度差异巨大** 下面是简化版伪代码展示大致思路框架图解说明如下所示: ```c void free(void *ptr){ if(!ptr)return; // NULL check mstate ar_ptr=get_mstate_for(ptr); // Get associated arena state. chunkptr p=mem2chunk(ptr); size_t sz=p->size&~NON_MAIN_ARENA; /* Handle small chunks via fast bins */ if(is_small(sz)){ unlink_and_set_fd(p,bins[idx]); return ; } /* Normal case processing including coalescing etc.*/ } ``` 以上仅为概念性的描述概括总结而已并非完整的精确再现真实情况下的全部复杂情形考虑因素众多难以一一列举穷尽所有可能性变化组合形式多样灵活适应性强等特点决定了它成为了一门深奥学问值得深入探究学习掌握精髓所在之处才能更好地运用自如游刃有余地解决问题克服困难挑战自我极限追求卓越成就非凡事业梦想成真辉煌未来无限美好前景广阔充满希望期待明天更加灿烂辉煌!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值