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

C-内存函数(大量图解,函数实现)

目录

一.memcpy

二.memmove

三.memcmp

四.memset


一.memcpy

头文件:

#include<string.h>

函数原型: 

功能解析:

  • 目的地址和源头地址,类型是void*可以接收任意类型
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的(在VS2022中,是不会出现重叠的

 函数模拟实现:

在实现函数前我们需要测试一下,几种常见的异常情况:

1.拷贝0字符

2.传入空指针

 我们再来看这个代码正常运行情况:

程序居然没有崩溃什么都没有发生

3.拷贝数传入负数

小数就不用多说了,类型都完全不同 

实现: 

  异常判断

void* my_memcpy(void* dest, const void* src, size_t num)
{	
	//异常判断

	if ((dest == NULL) || (src == NULL))
	{
		perror("my_memcpy");
		return NULL;//结束函数
	}
	if (num == 0)//如果拷贝0个直接返回目的地地址,就不用浪费时间了
	{
		return dest;
	}
}

 模拟实现:

void* my_memcpy(void* dest, const void* src, size_t num)
{	
	//异常判断
	if ((dest == NULL) || (src == NULL))
	{
		perror("my_memcpy");
		return NULL;
	}
	if (num == 0)
	{
		return dest;
	}
	//正常拷贝
	void* str = dest;
	while (num--)
	{
		*(char*)str = *(char*)src;
		src = (char*)src + 1;
		str = (char*)str + 1;
	}

	return dest;
}

运行结果: 

补充:!!! 

这个时候可能就有朋友会说,啊!你负数都没有处理,我也想过去处理发现各种方式都不行,后来才知道,有的时候就不用去处理,库里面的函数num是siz_t类型,你要传负数可以,那他就会变成一个很大的数,大不了就是栈溢出,栈溢出是你使用函数不当,我函数没有问题

还有一种情况,重合的空间:

1.前到后地址

 

 2.后到前地址

 我们得出结论:

  • 从前(低地址) -> 后(高地址)反方向拷贝
  • 从后(高地址) -> 前(低地址)从前拷贝

在C语言中用memmove函数就可以实现

二.memmove

函数头文件:

#include<string.h>

函数原型:

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

 模拟实现:

void* my_memmove(void* dest, const void* src, size_t num)
{
	//异常判断
	if ((dest == NULL) || (src == NULL))
	{
		perror("my_memcpy");
		return NULL;
	}
	if (num == 0)
	{
		return dest;
	}
	//正常拷贝
	void* str = dest;
	if (str < src)
	{
		while (num--)
		{
			*(char*)str = *(char*)src;
			src = (char*)src + 1;
			str = (char*)str + 1;
		}

	}
	else
	{
		while (num--)
		{
			*((char*)str + num) = *((char*)src + num);
		}
	}

	return dest;
}

代码段解析:

 代码结果: 

memmove:

memcpy:

但是在vs2022中memcpy也是可以完成重叠空间的拷贝的,这就得取决于编译器了

三.memcmp

函数头文件:

#include<string.h>

函数原型:

 返回值解析:

函数细节:

1.他是一个一个字节比较的,两个地址的字节相同,就比较下一个字节,一直比较到不同的,根据规定返回,或者到末尾返回0

函数实现准备:

老样子先去测试一下常见的一些意外情况

1.空指针

2.

3.num传入0

 4.num传入负数和上面的memcpy不处理就好

模拟实现:

1.意外判断

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
    //异常判断
	if ((ptr1 == NULL) || (ptr2 == NULL))
	{
		perror("my_memcmp:");
		return NULL;//结束函数
	}
	if (num == 0)
	{
		return -1;
	}
}

2. 正确实现

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	//意外判断
	if ((ptr1 == NULL) || (ptr2 == NULL))
	{
		perror("my_memcmp:");
		return NULL;//结束函数
	}
	if (num == 0)//如果没有这个if下面的返回值任然会计算
	{
		return -1;
	}
	//正常运转
	const char* str1 = (const char*)ptr1;
	const char* str2 = (const char*)ptr2;
	while ((*str1 == *str2) && (num > 0))//不大于0为假
	{
		str1++;
		str2++;
		num--;
	}
	
	if (*str1 - *str2 > 0) 
		return 1;
	else if (*str1 == *str2) 
		return 0;
	return -1;

	//也可以直接 return (*str1 - *str2);
}

运行结果:

 各种情况都是正确的


四.memset

头文件:

#include<string.h>

函数原型:

 函数使用:

1.

2.

 3.

制作不易,你们的支持是作者最大的动力!!!

相关文章:

  • 【STM32】MDK下的C语言基础
  • web前端面试题附答案041 - 曾经一个百度面试官问我,localStorage可以存对象吗?
  • 【Linux学习】权限
  • 基于AT89C51单片机的直流数字电压表设计
  • 脚本控制向Android模拟拨打电话,发送短信,定位设置功能
  • 深度理解微服务
  • 在 ABAP 开发工具运行时错误显示界面里植入思否猫
  • Matlab激光雷达相机联合标定经验分享
  • JVM<二>JVM调优(你想要的调优都在这里了)
  • Flowable监听器动态调用Springcloud接口
  • 数字电路和模拟电路-3二极管与三极管、基本逻辑运算
  • 机器学习——BP神经网络详细介绍及案例Python代码实现
  • 了解如何通过 UltraEdit丨UEStudio 中的窗口停靠系统显示、控制和配置文件选项卡
  • Flutter SDK 自带的 10 个最有用的 Widget
  • 计算机网络-应用层篇-HTTP协议
  • 08.Android之View事件问题
  • HTTP--网络协议分层,http历史(二)
  • idea + plantuml 画流程图
  • iOS 系统授权开发
  • Java深入 - 深入理解Java集合
  • leetcode-27. Remove Element
  • PAT A1017 优先队列
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • Redis 中的布隆过滤器
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Sequelize 中文文档 v4 - Getting started - 入门
  • springMvc学习笔记(2)
  • unity如何实现一个固定宽度的orthagraphic相机
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 动态魔术使用DBMS_SQL
  • 服务器从安装到部署全过程(二)
  • 后端_ThinkPHP5
  • 欢迎参加第二届中国游戏开发者大会
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 学习JavaScript数据结构与算法 — 树
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (分布式缓存)Redis哨兵
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (十八)SpringBoot之发送QQ邮件
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (一)插入排序
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .FileZilla的使用和主动模式被动模式介绍
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET 服务 ServiceController
  • .Net接口调试与案例
  • .NET设计模式(11):组合模式(Composite Pattern)