C语言——内存函数

前言:

C语言中除了字符串函数和字符函数外,还有一些函数可以直接对内存进行操作,这些函数被称为内存函数,这些函数与字符串函数都属于<string.h>这个头文件中。

一.memcpy()函数

memcpy是C语言中的一个内存函数,用来将source地址的num个字节复制到destination处。该函数可以处理任何数据,所以参数和返回值的类型都是void*。需要注意的是,该函数遇到\0之后不会停止,直到复制完num个字节。该函数要求目标地址的内存空间必须足够大,要能够容纳复制的内容。

虽然memcpy函数是有返回值的,但是我们可以选择不接受,这是没问题的。

如果源地址处没有num个字节,memcpy也不会停止,会顺着源地址向后寻找字节,直到复制完num个字节:

如上图所示,源地址只有16个字节,而memcpy函数却要复制20个字节的内容,这时候复制完16个字节之后会从该处继续向后复制四个字节,所以打印出来是随机值。

注意:memcpy处理重叠内存的复制,结果是未定义的。意思就是如果源地址与目标地址由重叠区域,就别用memcpy函数,虽然memcpy可以实现,但是有memmove函数专门来实现重复区域的复制。

1.memcpy的模拟实现

因为memcpy函数可以针对内存进行操作,那就说明它可以对任何数据进行复制,所以我们将参数设置成void*类型,以便接受各种类型的数据。

既然可以接受各种数据,那么怎么实现数据的复制呢?

我们可以将所有数据类型都转换成char*类型,我们只需要一个字节一个字节的复制就行了,因为我们知道一共要复制多少个字节,所以借助循环语句,将每个字节一一复制就行。

//memcpy函数的模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h>

void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);

	void* ret = destination;
	while (num--)
	{
		*(char*)destination = *(char*)source;
		destination = (char*)destination + 1;
		source = (char*)source + 1;
	}

	return ret;
}

int main()
{
	int nums1[] = { 1,2,3,4,5 };
	int nums2[20] = { 0 };

	my_memcpy(nums2, nums1, sizeof(int) * 5);

	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", nums2[i]);
	}
	return 0;
}

二.memmove()函数

该函数与memcpy的区别就在于,该函数可以处理重叠部分的内存复制。在处理两个毫不相关的内存复制的时候,功能与memcpy函数一摸一样。

在该函数中,arr是目标地址,arr+2是源地址,而要交换的是三个字节,这两个地址有重叠的部分,遇到要复制这种情况的就可以使用memmove函数。

1.memmove函数的模拟实现

该函数与memcpy的区别在于可以复制内存重叠部分,所以它可以算得上是memcpy的升级,既可以完成memcpy的功能,也可以完成它不可以完成的。

由图示可知,我们可以将重叠部分的复制分为两部分,源地址首地址小于目标地址,从后->前复制,反之由前->后。


//memmove函数的模拟实现

#include <stdio.h>
#include <assert.h>

void* my_memmove(void* destination, const void* source, size_t num)
{
	assert(destination && source);

	void* ret = destination;

	//前->后
	if (destination < source)
	{
		while (num--)
		{
			*(char*)destination = *(char*)source;
			destination = (char*)destination + 1;
			source = (char*)source + 1;
		}
	}
	//后->前
	else
	{
		while (num--)
		{
			*((char*)destination + num) = *((char*)source + num);
		}
	}
	return ret;
}

int main()
{
	//char str[] = "abcdef";
	int arr[] = { 1,2,3,4,5 };

	//char *ret1 = (char*)my_memmove(str+1, str, sizeof(char) * 3);
	char *ret2 = (char*)my_memmove(arr+1, arr, sizeof(int) * 3);

	//printf("%s\n", ret1-1);

	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

三.memset()函数

该函数的功能是将ptr地址中的num个字节修改设置成value值。

对于字符数组来说,一个字符占一个字节,故将5个字节修改成’1‘,就相当于将数组前五个元素设置成1。

四.memcmp()函数

memcmp的作用是比较ptr1和ptr2指向地址的num个字节的大小。

如果ptr1>ptr2,返回大于0的数;

ptr1 = ptr2,返回0;

ptr1<ptr2,返回小于0的数。

返回-1说明arr2第一个字节大于arr1的第一个字节。

图一左上角的是arr1的第一个字节,图二左上角是arr2的第一个字节,很显然4>1,所以函数返回-1。

完!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【OpenGL】(1) 环境搭建:运行简单的 OpenGL 教学示例程序

&#x1f4ad; 写在前面&#xff1a;我们尽可能地让大家以 最简单粗暴且无脑的方式&#xff0c;带大家配置好 OpenGL 环境&#xff0c;并跑出我们第一个示例程序。再次声明&#xff0c;本专栏所有教学都是基于 Windows上使用 VS2022 (X64) 的。本专栏主要内容是关于 3D 计算机图…

用数组模拟单链表、双链表、栈、单调栈、队列、循环队列、单调队列

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 目录 一.模拟单链表 二.双链表 三.栈 四.单调栈 五.队列 六.循环队列 七.单调队列 为什么要用数组模拟而不用现成的STL&#xff0c;因为用数组模拟效率会快一点&#xff0c;比如用结构体指针的方式创建链表&#xff0…

C++ 二叉树OJ题

&#x1f493;博主CSDN主页:麻辣韭菜-CSDN博客&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 前言 C二叉搜索树 这篇讲解了搜索二叉…

动态规划1

动态规划问题的五步操作&#xff1a; 动态规划就是把dp表填满&#xff0c;则最终一定有一个数据是我们所需要的数据 下面以一道简单的题目进行讲解 本题其实就是斐波那契数列的一个plus版 &#xff0c;就是利用递推关系求值的过程 1.前期准备&#xff1a;创建dp表(使用一维…

GRE和MGRE

思维导图 综合实验 配置IP地址 R1&#xff1a; [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 192.168.1.1 24 [R1-GigabitEthernet0/0/0]int s3/0/0 [R1-Serial3/0/0]ip add 15.1.1.1 24 R2: [R2]int g 0/0/0 [R2-GigabitEthernet0/0/0]ip ad 192.168.2.2 24 [R2-G…

基于四足机器人和机械臂的运动控制系统(二)

文章目录 前言一、四足步态二、视觉抓取三、远程遥控 谢绝转载&#xff0c;无作者许可不可用做其他用途&#xff08;如教育展示产品、课程设计或毕业设计等&#xff09; 前言 衔接上一篇文章&#xff0c;这篇文章主要来介绍项目的初步实现 一、四足步态 可以知道&#xff0…

常用的几种排序算法小结

目录 1.冒泡排序 2.堆排序 2.1堆的基础知识和特性 2.2向上调整算法和向下调整算法 2.3堆排序实现 3.插入排序 4.希尔排序 5.选择排序 5.1选择排序递归版 5.2选择排序非递归版 6.快速排序 6.1 Hoare版本之递归 6.1.1普通版 6.1.2随机数版 6.1.3三数取中版 6.1.4小区间优化…

前端虚拟滚动列表 vue虚拟列表

前端虚拟滚动列表 在大型的企业级项目中经常要渲染大量的数据&#xff0c;这种长列表是一个很普遍的场景&#xff0c;当列表内容越来越多就会导致页面滑动卡顿、白屏、数据渲染较慢的问题&#xff1b;大数据量列表性能优化&#xff0c;减少真实dom的渲染 看图&#xff1a;绿色…

安装最新的wxPython和Python3并保证二者兼容

要安装最新的wxPython和Python3并保证二者兼容&#xff0c;你可以按照以下步骤进行操作&#xff1a; 安装Python3&#xff1a; 访问Python官方网站下载适合你操作系统的最新版Python3安装包。运行安装程序&#xff0c;确保在安装过程中将Python添加到系统环境变量中。安装完成…

【Java】:static成员和代码块

目录 1.static成员 1.1再谈学生类 1.2static修饰成员变量 1.3static修饰成员方法 1.4static成员变量初始化 1.4.1就地初始化 1.4.2静态代码块初始化 2.代码块 2.1代码块概念以及分类 2.2普通代码块 2.3构造代码块 2.4静态代码块 1.static成员 1.1再谈学生类 使用类…

MATLAB 点云随机渲染赋色(51)

MATLAB 点云随机渲染赋色(51) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 为点云中的每个点随机赋予一种颜色,步骤和效果如图: 1、读取点云 (ply格式) 2、随机为每个点的RGB颜色字段赋值 3、保存结果 (ply格式) 二、算法实现 1.代码 代码如下(示例):…

gin基础学习笔记--参数验证

用gin框架的数据验证&#xff0c;可以不用解析数据&#xff0c;减少if else&#xff0c;会简洁许多。 package mainimport ("fmt""time""github.com/gin-gonic/gin""github.com/gorilla/sessions" )// 初始化一个cookie存储对象 // s…

基于STM32的武警哨位联动报警系统设计,支持以太网和WIFI通信

1.功能 本文提出的武警报警信息系统终端&#xff0c;可实现报警和联动响应&#xff0c;支持以太网和WIFI两种通信模式&#xff0c;可实现移动哨位报警和固定哨位报警&#xff0c;语音和显示报警信息用户可自行定制。 本终端主要由STM32F103处理器模块和C8051F340处理器模块构…

P-MapNet:Far-seeing Map Generator Enhanced by both SDMap and HDMap Priors

主页&#xff1a;homepage 参考代码&#xff1a;P-MapNet 动机与出发点 在感知系统中引入先验信息是可以提升静态元素感知网络的上限的&#xff0c;这篇文章对SD地图采用栅格化表示&#xff08;也就是图像形式&#xff09;&#xff0c;之后用CNN网络去抽取栅格化SD地图的信息&…

linux ubuntu 在保存文件不被允许,但是root权限

现象&#xff1a;MobaXterm_Personal_2登录到服务器&#xff0c;切换到root用户&#xff0c;然后使用MobaXterm_Personal_2自带的编辑器&#xff0c;编写文件&#xff0c;进行保存不被允许&#xff1b;查看目录root是有权限进行修改文件的&#xff0c;然后使用vim进行修改保存&…

网络安全-内网渗透2

一、MIC 将我们上次未描述完的MIC在这里详细解释一下 咱们所抓的第二个包会给返回一个服务端的challenge 之后服务器回包的第三个包会回复一个client challenge 所以咱们客户端和服务端现在分别有两个challenge&#xff0c;相当于客户端和服务端互相交换了一下challenge 因此…

本地搭建多人协作ONLYOFFICE文档服务器并结合Cpolar内网穿透实现公网访问远程办公

文章目录 1. 安装Docker2. 本地安装部署ONLYOFFICE3. 安装cpolar内网穿透4. 固定OnlyOffice公网地址 本篇文章讲解如何使用Docker在本地服务器上安装ONLYOFFICE&#xff0c;并结合cpolar内网穿透实现公网访问。 Community Edition允许您在本地服务器上安装ONLYOFFICE文档&…

高精度(大整数)

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 一.什么是大整数 当一个数的位数已经很大了&#xff08;比如有10^6&#xff09;&#xff0c;常规的数据类型已经存不下了&#xff0c;那么这个时候就可以用数组来存&#xff0c;数组的每个元素代表数的每一位&#xff0c;且…

Base64编码的全面介绍

title: Base64编码的全面介绍 date: 2024/3/31 18:55:49 updated: 2024/3/31 18:55:49 tags: Base64编码网络传输文本转换数据膨胀非加密性质应用场景安全传输 1. Base64的定义和作用 Base64是一种用64个字符表示二进制数据的编码方式&#xff0c;通常用于在网络传输中将二进…

什么是Redis数据一致性?如何解决?

在系统中缓存最常用的策略是&#xff1a;服务端需要同时维护DB和cache&#xff0c;并且是以DB的结果为准–Cache-Aside Pattern&#xff08;缓存分离模式、旁路缓存&#xff09; 读数据 单纯的读数据是不会产生数据不一致&#xff0c;只有并发下读和写才会存在数据不一致。 写…