C语言:内存函数

news2024/11/17 8:15:38

创作不易,友友们给个三连吧!!

C语言标准库中有这样一些内存函数,让我们一起学习吧!!

一、memcpy函数的使用和模拟实现

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

1.1 使用的注意事项 

1、函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

2、这个函数在遇到 '\0' 的时候并不会停下来。

3、如果source和destination有任何的重叠,复制的结果都是未定义的。

4、返回的是目标空间的地址(destination)

5、memcpy函数可以实现整型拷贝、字符拷贝、结构体拷贝等等,所以参数和返回值都是void*

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 5 * sizeof(int));//将1、2、3、4、5 拷贝到arr2中
	for (int i = 0; i < 10; i++)
		printf("%d ", arr2[i]);
	return 0;
}

输出结果:1 2 3 4 5 0 0 0 0 0 

如果我想将 4 5 6 7 8 拷贝到arr2呢???

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1+3, 5 * sizeof(int));//将4 5 6 7 8拷贝到arr2中
	for (int i = 0; i < 10; i++)
		printf("%d ", arr2[i]);
	return 0;
}

输出结果:4 5 6 7 8 0 0 0 0 0

这说明我们可以通过指针的加减来改变我们在数组中的接收地址 

1.2 memcpy的模拟实现 

void* my_memcpy(void* des, const void* src, size_t num)
{
	assert(des && src);//确保不传NULL进来
	void* ret = des;//记住返回值
	//因为memcpy实现的是任何数据类型的拷贝,且num是字节,所以强转成char*进行运算最合适
	while (num--)
	{
		//一次拷贝一个字节
		*(char*)des = *(char*)src;//
		//迭代   因为强制类型转化的效果是临时的,要一直强转才能运算
		des = (char*)des + 1;
		src = (char*)src + 1;
	}
	return ret;
}

二、memmove函数的使用和模拟实现

C语言规定:memcpy拷贝的是不重叠的内存,而memmove拷贝的是重叠的内存

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

       虽然在vs2022中memcpy也是可以拷贝重叠内存的,但是其他编译器就不一定了,所以我们在使用的时候,尽量是不重叠的用memcpy,重叠的用memmove

2.1 使用的注意事项

1、和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。

2、如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memmove(arr1+2, arr1, 5 * sizeof(int));//将1、2、3、4、5 拷贝到原来3、4、5、6、7的位置
	for (int i = 0; i < 10; i++)
		printf("%d ", arr1[i]);
	return 0;
}

输出结果:1 2 1 2 3 4 5 8 9 10 

2.2 memmove的模拟实现

void* my_memmove(void* dst, const void* src, size_t num)
{
	assert(dst && src);//确保不传NULL进来
	void* ret = dst;//记住返回值
	if (dst < src)//从前往后,和memcpy一样
	{
		while (num--)
		{
			//一次拷贝一个字节
			*(char*)dst = *(char*)src;//
			//迭代   因为强制类型转化的效果是临时的,要一直强转才能运算
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else//从后往前
		while (num--)
			//要跳num-1个字节
			*((char*)dst + num) = *((char*)src + num);
		return ret;
}

三、memset函数的使用和模拟实现

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

 3.1 使用的注意事项

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

int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

输出结果:xxxxxxworld 

注意:该函数是以字节为单位操作的

如果我们操作的是int类型的数组会怎样???

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	memset(arr, 1, 10);
	for (int i = 0; i < 10; i++)
		printf("%d ", arr[i]);
	return 0;
}

输出结果: 16843009 16843009 257 4 5 6 7 8 9 10 

为什么会是这样的结果??下面进行分析 

 3.2 memset的模拟实现

void* my_memset(void* ptr, int value, size_t num)
{
	while (num--)
	{
		*(char*)ptr = value;
		ptr = (char*)ptr + 1;
	}
}

四、memcmp函数的使用

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

1、⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节

2、返回值如下:

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 1,2,3,8 };
	printf("%d\n", memcmp(arr1, arr2, 12));
}

输出结果:0 

如果我们比较13个字符呢??

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 1,2,3,8 };
	printf("%d\n", memcmp(arr1, arr2, 13));
}

 输出结果:-1

    因为小端存储,所以arr1的第13个字节存储的是04,而arr2的第13个字节存储的是08,所以返回-1!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1435674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高速接口PCB布局指南(二)通用高速信号布线

高速接口PCB布局指南&#xff08;二&#xff09;通用高速信号布线 1.PCB材料编织2.高速信号布线长度3.高速信号布线长度匹配4.高速信号参考平面 tips&#xff1a;资料主要来自网络&#xff0c;仅供学习使用。 1.PCB材料编织 在常见的 PCB 材料上为差分信号布线时&#xff0c;…

基于SSM的协同过滤技术的网上书城(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的协同过滤技术的网上书城&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Sp…

深入理解vqvae

深入理解vqvae TL; DR&#xff1a;通过 vector quantize 技术&#xff0c;训练一个离散的 codebook&#xff0c;实现了图片的离散表征。vqvae 可以实现图片的离散压缩和还原&#xff0c;在图片自回归生成、Stable Diffusion 中&#xff0c;有重要的应用。 从 AE 和 VAE 说起 …

【Nicn的刷题日常】之打印整数二进制的奇数位和偶数位

目录 1.题目描述 2.解题思路 3.解题 1.题目描述 获取一个整数二进制序列中所有的偶数位和奇数位&#xff0c;分别打印出二进制序列 2.解题思路 1. 提取所有的奇数位&#xff0c;如果该位是1&#xff0c;输出1&#xff0c;是0则输出0 2. 以同样的方式提取偶数位置检测n…

k8s学习(RKE+k8s+rancher2.x)成长系列之简配版环境搭建(二)

三、简配版集群&#xff0c;适用于demo环境 1.集群架构设计 主机名角色配置(核数&#xff0c;内存&#xff0c;磁盘)MasterRKE,controlplane,etcd,worker,rancher-master2C 8G 40GSlaver1controlplane,worker,rancher-master2C 8G 40GSlaver2controlplane,worker,rancher-mas…

ES6 ~ ES11 学习笔记

课程地址 ES6 let let 不能重复声明变量&#xff08;var 可以&#xff09; let a; let b, c, d; let e 100; let f 521, g "atguigu", h [];let 具有块级作用域&#xff0c;内层变量外层无法访问 let 不存在变量提升&#xff08;运行前收集变量和函数&#…

MATLAB | 绘图复刻(十四) | 右侧对齐桑基图,及工具函数SSankey更新

hey 真的好久不见了&#xff0c;本期既是一期绘图复刻教程&#xff0c;也是我写的工具函数的版本更新&#xff0c;本期复刻的图片来自《Nature》&#xff1a; Elmarakeby, H.A., Hwang, J., Arafeh, R. et al. Biologically informed deep neural network for prostate cancer…

C++学习Day04之this指针

目录 一、程序及输出1.1 基础使用1.2 *this和链式编程1.2.1 返回引用进行链式编程1.2.2 返回值进行链式编程1.3 注意事项 二、分析与总结 一、程序及输出 在 C 中使用类的成员函数时&#xff0c;可以使用 this 指针来引用当前对象的地址。this 指针是一个隐式参数&#xff0c;它…

计算机视觉-PCV包、Vlfeat库、Graphviz库的下载安装配置及问题解决(使用anaconda3 python 3.8.5)

目录 一、PCV包配置 二、Vlfeat配置 三、在PCV包的sift.py文件中对路径进行修改 四、以上步骤所需注意的错误 五、Graphviz配置 一、PCV包配置 1.下载PCV包,点开网址直接下载安装包(不用解压),下载之后将安装包放在任意目录位置https://codeload.github.com/Li-Shu14…

JavaEE作业-实验一

目录 1 实验内容 2 思路 3 核心代码 &#xff08;1&#xff09;前端核心代码&#xff1a; &#xff08;2&#xff09;后端核心代码&#xff1a; 4 实验结果 1 实验内容 用Servlet JSP JavaBean实现登录功能 2 思路 ①建好web项目,创建数据库 ②建立两个简单的前端页…

【为什么多态中父类要提供虚析构函数?】

为什么多态中父类要提供虚析构函数&#xff1f; 不提供虚析构函数提供虚析构函数 如果说类与类之间产生了继承关系&#xff0c;并且在子类中重写了父类的虚函数&#xff0c;相当于最终要实现多态&#xff0c;就是用父类指针或引用指向子类的对象&#xff0c;并且通过父类指针调…

算法学习——LeetCode力扣链表篇1

算法学习——LeetCode力扣链表篇1 203. 移除链表元素 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 示例 …

爬虫实战--人民网

文章目录 前言发现宝藏 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#xff0c;如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚&#xff0c;文章中如果有记录错误&#xff0c;欢迎读者朋友们…

【C语言不能不会的操作】调试-万字详解【windows操作系统下】(会写bug还会调试解决bug的程序员简直帅呆了,赶紧点赞收藏)

目录 1. 什么是bug&#xff1f; 2. 调试是什么&#xff1f;有多重要&#xff1f; 2.1调试是什么 2.2 调试的基本步骤 2.3 Debug和Release的介绍 3. Windows环境调试介绍 3.1 调试环境的准备 3.2 学会快捷键 ​编辑 3.3更多的快捷键 3.4 调试的时候查看程序当前信息…

【lesson41】理解文件系统(2)

文章目录 理解文件系统 理解文件系统 我们之前学过&#xff0c;一个文件可以有多个datablock块&#xff0c;但是如果这个文件太大了怎么办&#xff1f;datablock中&#xff0c;不是所有的datablock只能存文件数据&#xff0c;也可以存其它块的块号。 inode Vs 文件名 找到文件…

MySQL数据库③_MySQL数据类型和测试

目录 1. MySQL数据类型分类 1.1 类型汇总 1.2 整数类型 1.3 浮点数类型和定点数类型 1.4 字符串类型和文本类型 1.5 日期与时间类型 1.6 二进制类型 2. 有代表的类型测试 2.1 tinyint类型 2.2 bit类型 2.3 float类型 2.4 decimal类型 2.5 char和varchar类型 2.6 …

Vue3快速上手(一)使用vite创建项目

一、准备 在此之前&#xff0c;你的电脑&#xff0c;需要安装node.js,我这边v18.19.0 wangdymb 2024code % node -v v18.19.0二、创建 执行npm create vuelatest命令即可使用vite创建vue3项目 有的同学可能卡主不动&#xff0c;可能是npm的registry设置的问题 先看下&#x…

为后端做准备

这里写目录标题 flask 文件上传与接收flask应答&#xff08;接收请求&#xff08;文件、数据&#xff09;flask请求&#xff08;上传文件&#xff09;传递参数和文件 argparse 不从命令行调用参数1、设置default值2、"从命令行传入的参数".split()3、[--input,内容] …

备战蓝桥杯---数据结构与STL应用(进阶2)

本文将主要围绕有关map的今典应用展开&#xff1a; 下面我用图进行分析&#xff1a; 下面为AC代码&#xff1a; #include<bits/stdc.h> using namespace std; struct Point {int x,y;bool operator < (const Point & r) const {return x < r.x || ( x r.x &a…

【Java八股面试系列】JVM-垃圾回收

目录 垃圾回收 堆空间的基本结构 内存分配和回收原则 分代收集机制 Minor GC 流程 空间分配担保 老年代 大对象直接进入老年代 长期存活的对象将进入老年代 GC的区域 对象存活判定算法 引用计数法 可达性分析算法 finalize() 字符串常量判活 类判活 垃圾回收算…