探索内存函数的奥秘【memcpy、memmove、memset、memcmp】

目录

一,memcpy函数

1,memcpy函数简介

2,memcpy函数的原理

3,memcpy函数的用法

4,注意事项

5,memcpy函数模拟实现

二,memmove函数

1,memmove函数简介

2,memmove函数的原理

3,memmove函数的用法

4,注意事项

5,memmove函数模拟实现

三,memset函数

1,memset函数简介

2, memset函数的原理

3,memset函数的用法

4,注意事项

四,memcmp函数

1,memcmp函数简介

2,memcmp函数功能

3,memcmp函数的用法 


一,memcpy函数

1,memcpy函数简介

memcpy函数的作用是将源内存块的内容复制到目标内存块中。

🌴函数头文件: 

#include <string.h>

 🌴函数原型:

void * memcpy ( void * destination, const void * source, size_t num );
  • dest:目标内存块的起始地址。
  • src:源内存块的起始地址。
  • num:要拷贝的字节数。
  • 该函数返回指向目标内存块的指针。

2,memcpy函数的原理

  • 它通常采用字节拷贝的方式来实现内存块的复制
  • 具体来说,memcpy函数会从源内存块中逐个字节地读取数据,并将其逐个字节地写入目标内存块中,直到拷贝完成为止。
  • 由于这种逐字节的拷贝方式,memcpy函数在处理大内存块时可能会比较耗时,因此在一些情况下可能会有更高效的替代方案。

3,memcpy函数的用法

将arr1数组里边的数(在内存中占20个字节)拷贝到arr数组里边去。

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

int main()
{
	int arr[10] = { 0 };
	int arr1[] = { 1,2,3,4,5 };

	memcpy(arr, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

 🌴运行结果:

4,注意事项

  1. 内存重叠: 源内存块和目标内存块通常不应该重叠,否则会导致未定义的行为。

  2. 边界检查:需要确保拷贝的字节数不超过源内存块和目标内存块的实际大小,以免发生越界访问。

  3. 指针类型:需要注意指针类型的转换,确保传递给memcpy函数的参数类型正确。

5,memcpy函数模拟实现

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

void* my_memcpy(void* dest, void* src, size_t sz)
{
    void* ret = dest;
	assert(dest && src);
	while (sz--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
    return ret;
}

int main()
{
	int arr[10] = { 0 };
	int arr1[] = { 1,2,3,4,5 };
	my_memcpy(arr, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

二,memmove函数

1,memmove函数简介

memmove函数的作用是将源内存块的内容移动到目标内存块中。与memcpy函数不同的是,memmove函数能够处理源内存块和目标内存块重叠的情况。

 🌴函数头文件:

#include <string.h>

 🌴函数原型:

void * memmove ( void * destination, const void * source, size_t num );
  • dest:目标内存块的起始地址。
  • src:源内存块的起始地址。
  • num:要移动的字节数。
  • 该函数返回指向目标内存块的指针。

2,memmove函数的原理

  • memmove 函数的实现原理会比memcpy稍微复杂一些,因为它需要处理源内存块和目标内存块重叠的情况。
  • 通常,memmove函数会采用一种类似于缓冲区的机制,先将源内存块的内容复制到一个临时缓冲区中,然后缓冲区的内容复制到目标内存块中,从而避免了重叠拷贝导致的数据错乱。
  • 这种机制使得memmove函数在处理重叠内存块时能够保证正确的移动操作。

3,memmove函数的用法

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

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;

  🌴运行结果:

4,注意事项

  1. 内存重叠: 虽然memmove函数能够处理重叠的内存块,但仍需谨慎处理,以免出现意外的情况。

  2. 边界检查:确保拷贝的字节数不超过源内存块和目标内存块的实际大小,以免发生越界访问。

  3. 指针类型:需要注意指针类型的转换,确保传递给memmove函数的参数类型正确。

5,memmove函数模拟实现

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

void* my_memmove(void* dest, const void* src, size_t sz)
{
	void* ret = dest;
	assert(dest && src);

	if (dest < src)
	{
		//前->后
		while (sz--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

三,memset函数

1,memset函数简介

memset函数的作用是将指定内存块的内容设置为指定的值。

 🌴函数头文件:

#include <string.h>

  🌴函数原型:

void * memset ( void * ptr, int value, size_t num );
  •  ptr:指向要设置数值的内存块的指针
  • value:要设置的值
  • num:要设置的字节数
  • 该函数返回值指向内存块的指针

2, memset函数的原理

  •  通常使用一个循环来逐个字节地设置内存块的内容为指定的值
  • 由于内存的底层表示是字节,因此逐字节设置是一种通用且高效的方法
  • 在某些特定的平台上,memset函数可能会进行一些优化,以提高性能

3,memset函数的用法

🍁示例1:初始化数组:

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

int main()
{
	int arr[5];
	
	//将数组所有的元素初始化为0
	memset(arr, 0, sizeof(arr));
	for (int i = 0; i < 5; i++)
	{
		printf("%d", arr[i]);
	}

	return 0;
}

   🌴运行结果:


🍁示例2:清空字符串: 

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

int main()
{
	char str[] = "hello world";

    //将字符串str的所有字符设置为0
	memset(str, 0, sizeof(str));

    //输出空字符串
	printf("%s\n", str);

	return 0;
}

    🌴运行结果:

🌴调试时内存中情况: 


🍁示例3:内存分配和释放: 

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

int main()
{
	char* str = (char*)malloc(10 * sizeof(char));

	//对动态分配的内存进行初始化
	memset(str, 0, 10 * sizeof(char));
	strcpy(str, "hello");
	printf("%s\n", str);//输出:hello
	free(str);//释放内存

	return 0;
}

     🌴运行结果:

4,注意事项

  • 内存越界:确保设置的字节数不超过内存块的实际大小,以避免发生越界访问

  • 指针类型:需要注意指针类型的转换,确保传递给memset函数的参数类型正确

  • 对结构体和类的使用:在对结构体和类的内存块进行初始化时,需要谨慎处理,以避免出现意外的情况 

四,memcmp函数

1,memcmp函数简介

memcmp函数可以比较两个内存块的内容是否相等,并返回比较结果,通常用于比较字符串、数组或者其它内存块的内容。

  🌴函数头文件:

#include <string.h>

  🌴函数原型:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • ptr1:要比较的第一个内存块的起始地址。
  • ptr2:要比较的第二个内存块的起始地址。
  • num:要比较的字节数。

2,memcmp函数功能

  • 按字节逐个比较两个内存块中的内容,直到比较了num个字节或者遇到不相等的字节为止。

  • 如果两个内存块的内容完全相等,则返回0。

  • 如果第一个内存块小于第二个内存块,则返回一个负数。

  • 如果第一个内存块大于第二个内存块,则返回一个正数。 

3,memcmp函数的用法 

🍂示例1:比较字符串:

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

int main()
{
	char str1[] = "hello";
	char str2[] = "world";
	if (memcmp(str1, str2, 5) == 0)
	{
		printf("两个字符串相等\n");
	}
	else
	{
		printf("两个字符串不相等\n");
	}

	return 0;
}

   🌴运行结果:


🍂示例2:比较数组:

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

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	if (memcmp(arr1, arr2, 5 * sizeof(int) == 0))
	{
		printf("两个数组相等\n");
	}
	else
	{
		printf("两个数组不相等\n");
	}

	return 0;
}

   🌴运行结果:

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

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

相关文章

实验室(检验科)信息系统源码,医学检验LIS系统源码,云LIS源码

实验室&#xff08;检验科&#xff09;信息系统源码&#xff0c;LIS源码&#xff0c;基于云计算技术的LIS系统源码&#xff0c;云LIS源码 LIS系统(LaboratoryInformationSystem) 即 实验室&#xff08;检验科&#xff09;信息系统&#xff0c;它是医院信息管理的重要组成部分之…

Vue3 源码解读系列(三)——组件渲染

组件渲染 vnode 本质是用来描述 DOM 的 JavaScript 对象&#xff0c;它在 Vue 中可以描述不同类型的节点&#xff0c;比如&#xff1a;普通元素节点、组件节点等。 vnode 的优点&#xff1a; 抽象&#xff1a;引入 vnode&#xff0c;可以把渲染过程抽象化&#xff0c;从而使得组…

用 winget 在 Windows 上安装 kubectl

目录 kubectl 是什么&#xff1f; 安装 kubectl 以管理员身份打开 PowerShell 使用 winget 安装 kubectl 测试一下&#xff0c;确保安装的是最新版本 导航到你的 home 目录&#xff1a; 验证 kubectl 配置 kubectl 是什么&#xff1f; kubectl 是 Kubernetes 的命令行工…

38 路由的过滤器配置

3.3.断言工厂 我们在配置文件中写的断言规则只是字符串&#xff0c;这些字符串会被Predicate Factory读取并处理&#xff0c;转变为路由判断的条件 例如Path/user/**是按照路径匹配&#xff0c;这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoute…

计算机毕业设计:水果识别检测系统 python 深度学习 YOLOv5

[毕业设计]2023-2024年最新最全计算机专业毕设选题推荐汇总 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多的人 。 1、项目介绍 本文介绍了一种基于深度学习的水果检测与识别系统…

移动端模型部署框架

移动端模型部署框架 1. MNN整体特点轻量性通用性高性能易用性架构设计主体工具致谢移动端模型部署框架 1. MNN https://www.yuque.com/mnn/cn/about MNN是全平台轻量级高性能深度学习引擎,广泛支持了阿里巴巴在计算机视觉、语音识别技术、自然语言处理等领域的70多个AI应用…

【Java 进阶篇】Java中的 JSP(JavaServer Pages)

JavaServer Pages&#xff08;JSP&#xff09;是一种用于开发动态Web页面的Java技术。它是在静态Web页面中嵌入Java代码的一种方式&#xff0c;使得开发者可以借助Java的强大功能来创建动态、交互性强的Web应用程序。在本文中&#xff0c;我们将深入探讨JSP的概念、原理和基本用…

MYSQL内容补充:

一)联合索引: 1)定义:是给一张表上面的多个列增加索引&#xff0c;也就是说给表上面的多个列增加索引&#xff0c;供快速查询使用&#xff0c;当两个列的组合是唯一值时&#xff0c;联合索引是个不错的选择 联合索引和单个索引对比来讲&#xff0c;联合索引的所有索引项都会出现…

重温数据结构与算法之前缀和

文章目录 前言一、基础1.1 定义1.2 时间复杂度 二、扩展2.1 二维前缀和2.2 差分数组2.3 前缀积 三、LeetCode 实战3.1 长度最小的子数组3.2 二维区域和检索 - 矩阵不可变 参考 前言 前缀和&#xff08;Prefix Sum&#xff09;&#xff0c;也被称为累计和&#xff0c;是一种在计…

SQL必知会(二)-SQL查询篇(5)-用通配符进行过滤

第6课、用通配符进行过滤 LIKE&#xff1a;匹配文本 LIKE&#xff1a;针对未知值进行过滤。通配符搜索只能用于文本字段。 1&#xff09;百分号%通配符 %表示任何字符出现任意次数。 需求&#xff1a;找出所有以词 Fish 起头的产品 SELECT prod_id, prod_name FROM Product…

浅谈高并发以及三大利器:缓存、限流和降级

引言 高并发背景 互联网行业迅速发展&#xff0c;用户量剧增&#xff0c;系统面临巨大的并发请求压力。 软件系统有三个追求&#xff1a;高性能、高并发、高可用&#xff0c;俗称三高。三者既有区别也有联系&#xff0c;门门道道很多&#xff0c;全面讨论需要三天三夜&#…

Aria2 任意文件写入漏洞复现

漏洞描述 Aria2 是一款轻量级、多协议、多源下载工具&#xff08;支持 HTTP/HTTPS、FTP、BitTorrent、Metalink&#xff09;&#xff0c;内置 XML-RPC 和 JSON-RPC 接口。 我们可以使用 RPC 接口来操作 aria2 并将文件下载到任意目录&#xff0c;从而造成任意文件写入漏洞。 …

Nginx常用配置与命令,nginx代理转发配置

Nginx特点 高并发、高性能; 模块化架构使得它的扩展性非常好; 异步非阻塞的事件驱动模型这点和 Node.js 相似; 相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性; 热部署、平滑升级; 完全开源,生态繁荣; Nginx作用 Nginx 的最重要的…

【Excel】补全单元格值变成固定长度

我们知道股票代码都为6位数字&#xff0c;但深圳中小板代码前面以0开头&#xff0c;数字格式时前面的0会自动省略&#xff0c;现在需要在Excel表格补全它。如下图&#xff1a; 这时我们需要用到特殊的函数&#xff1a;TEXT或者RIGHT TEXT函数是Excel中一个非常有用的函数。TEX…

SpringBoot项目调用openCV报错:nested exception is java.lang.UnsatisfiedLinkError

今天在通过web项目调用openCV的时候提示如下错误&#xff1a; nested exception is java.lang.UnsatisfiedLinkError:org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/la如下图所示&#xff1a; 但是通过直接启动java main函数确正常&#xff0c;初步诊断和SpringBoot热加载…

dart packages 版本问题解决 和 对 pubspenc.lock 的深入了解

先讲讲我遇到的问题 在进行写项目的时候&#xff0c;我需要用到一个依赖 这个依赖是 3.0.0 版本的&#xff0c;但是实际上我本地的上存在多个版本 虽然我修改了 pubspenc.yaml 文件中需要的依赖&#xff0c;但是每次使用的还是 3.4.0 版本的依赖&#xff0c;但是我需要的是 3…

Windows查看端口占用情况

Windows如何查看端口占用情况 方法1. cmd命令行执行netstat命令&#xff0c;查看端口占用情况 netstat -ano 以上命令输出太多信息&#xff0c;不方便查看&#xff0c;通过如下命令搜索具体端口占用情况&#xff0c;例如&#xff1a;8080端口 netstat -ano | findstr "…

手摸手入门Springboot+Grafana10.2接收JSON

JSON&#xff08;JavaScript Object Notation, JS对象简谱&#xff09;是一种轻量级的数据交换格式。它基于 ECMAScript&#xff08;European Computer Manufacturers Association, 欧洲计算机协会制定的js规范&#xff09;的一个子集&#xff0c;采用完全独立于编程语言的文本…

面向对象基础(以python语言为例)

1、定义一个类&#xff1b;实例化类的对象&#xff1b;调用类中的方法 #定义一个类 class Student:#类方法&#xff08;即函数&#xff09;def study(self,course_name):print(f学生正在学习{course_name})def play(self):print("xx学生正在玩游戏")#实例化&#xf…

Rust的崛起:现代必备编程语言,是时候该考虑加入学习了

在不断变化的编程环境中&#xff0c;新的语言和框架如雨后春笋般涌现&#xff0c;需要一个真正强大且设计良好的工具才能脱颖而出。在这些工具中&#xff0c;Rust 已成为效率、安全性和性能的灯塔。从它作为 Mozilla 的一个副项目到它在软件行业中不可否认的增长&#xff0c;Ru…