C语言内存函数的理解

本文详细介绍了C语言中的四个重要内存管理函数:memcpy(复制)、memmove(移动)、memset(设置)和memcmp(比较)。特别关注了它们在处理重叠内存时的行为,并提供了函数的模拟实现示例。
摘要由CSDN通过智能技术生成

一、简单了解

C语言内存函数有以下几个重要的:
1.memcpy( 复制内存块功能 )
2.memmove(移动内存块函数)
3,memset(设置内存函数)
4.memcmp(比较两个内存块函数)

二、各个函数的深层次理解

1、memcpy函数

 void * memcpy ( void * destination, const void * source, size_t num );

这是函数的基本参数
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 ‘\0’ 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。

#include <stdio.h>
#include <string.h>
int main()
{
 int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
 int arr2[10] = { 0 };
 memcpy(arr2, arr1, 20);
 int i = 0;
 for (i = 0; i < 10; i++)
 {
 printf("%d ", arr2[i]);
 }
 return 0;
}

上述代码会打印1,2,3,4,5,0,0,0,0,0.
在这里插入图片描述
为什么会这样呢?
memcpy(arr2, arr1, 20);因为这里的20并不是20个数字,而是20个字节,我们定义的是int类型的数组,int是四个字节,20个字节也就是五个数字;对于之后的五个数字就会根据初始化打印‘0’;
而 对于重叠的内存,交给memmove来处理。

memcpy函数的模拟实现
void * memcpy ( void * dst, const void * src, size_t count)
{
 void * ret = dst;
 assert(dst);
 assert(src);
 /*
 * copy from lower addresses to higher addresses
 * 即从较低地址复制到较高地址
 */
 while (count--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst + 1;
 src = (char *)src + 1;
 }
 return(ret);
}

首先用ret接受dst数组,再分别断言两个数组不能为空,
紧接着进入循环,先将两个数组强制转换成char*类型,分别解引用并判断相等;//目的是让两个数组一个字节一个字节的访问下去
再让两个数组++一步一步向后走,直到count=0退出循环
最后返回ret。

2、memmove函数

void * memmove ( void * destination, const void * source, size_t num );

• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
• 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。

#include <stdio.h>
#include <string.h>
int main()
{
 int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
 memmove(arr1+2, arr1, 20);
 int i = 0;
 for (i = 0; i < 10; i++)
 {
 printf("%d ", arr1[i]);
 }
 return 0}

在这里插入图片描述

同样的,这里的20也是20个字节,五个数字。

memmove的模拟实现
void * memmove ( void * dst, const void * src, size_t count)
{
 void * ret = dst;
 if (dst <= src || (char *)dst >= ((char *)src + count)) {
 /*
 * Non-Overlapping Buffers
 * copy from lower addresses to higher addresses
 */
 while (count--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst + 1;
 src = (char *)src + 1;
 }
 }
 else {
 /*
 * Overlapping Buffers
 * copy from higher addresses to lower addresses
 */
 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);
}

整理框架是一个if语句的判断,判断dst和src 的大小,强制转换位char*类型,逐个字节访问,当符合条件的时候和momcpy一样进行循环,当不符合的时候基本是相反的,逐个字节判断,最后返回输出;

3、memset函数

void * memset ( void * ptr, int value, size_t num );

memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

 #include <stdio.h>
#include <string.h>
int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

输出:
xxxxxxworld
在这里插入图片描述
memset (str,‘x’,6);
将str数组中的前六个字符变成‘x’;

4、memcmp函数

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节
• 返回值如下:
在这里插入图片描述

在这里插入图片描述
因为DWgAOtp12Df0 大于 DWGAOTP12DF0,因为两个单词中的第一个不匹配字符分别是“g”和“G”,并且“g”(103)的计算结果大于“G”(71)。

  • 49
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值