C语言内存函数

一、memcpy使用和模拟实现

函数原型:

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

 dest指向目标内存区域的指针,即数据要复制的地方。sour指向内存区域的指针,即数据要复制的地方。num要复制的字节数。

memcpy函数会将sour所指向的内存区域的前num个字节复制到dest所指向的内存区域。这个函数不会检查目标内存是否有足够的空间来存储复制的数据,也不会检查源内存区域和目标内存区域是否重叠。如果重叠,结果是未定义的,在这种情况下应该使用memmove函数。

#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9 };int arr2[10] = { 0 };memcpy(arr2,arr1, 5 * sizeof(int));        //这里的num也可以直接填想复制多少字节for (size_t i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

 下面是错误例子也就是上面讲的源内存空间和目标内存空间重叠部分

#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9 };int arr2[10] = { 0 };memcpy(arr1+3, arr1+4, 5 * sizeof(int));		//在vs编译器中虽然可以编译重叠的部分但是在其他开发环境可能无法实现(重叠不仅仅指完全重叠就算有一个字节重叠也是不行),这个时候我们就要使用memmove来实现重叠部分的拷贝。for (size_t i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

下面是模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num) {void* p = dest;assert(dest && src);        //assert是用于避免空指针,如果有空指针就会停止while (num--) {        //num是指一共要交换多少字节。下面的内容是按字节交换*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return p;
}
int main() {int arr1[10] = { 1,2,3,4,5,6,7,8,9 };int arr2[10] = { 0 };my_memcpy(arr2, arr1+4, 5 * sizeof(int));	for (size_t i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

二、memmove使用和模拟实现

函数原型:

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

头文件<string.h>

memmove函数从源内存区域src复制n个字节的数据到目标内存区域dest。与memcpy不同的是memmove可以正确的处理源和目标区域重叠的情况。它会将源数据复制到一个临时区域,然后在从临时区域复制到目标区域,以此避免数据覆盖问题。

#include <stdio.h>
#include<string.h>
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };memmove(arr1+2, arr1, 5*sizeof(int));        //memmove函数就可以完美解决源和目标区域重叠的问题(即使在其他开发环境也能实现)for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

 我们先在来模拟实现memmove函数

#include <stdio.h>// 模拟实现memmove函数void* my_memmove(void* dest, const void* src, size_t n) {char* ret = (char*)dest;char* d = (char*)dest;const char* s = (const char*)src;// 如果源地址和目标地址相同,直接返回目标地址if (d == s) {return dest;}// 如果目标地址在源地址之后,为避免数据覆盖,从后往前复制if (d > s) {while (n--) {*(d + n) = *(s + n);}}else {// 否则,从前往后复制while (n--) {*d = *s;d++;s++;}}return dest;
}// 测试代码int main() {char str1[14] = "Hello, World!";char str2[20];// 测试不重叠的情况my_memmove(str2, str1, sizeof(str1));printf("Non-overlapping copy: %s\n", str2);// 打印重叠复制前的字符串printf("Before overlapping copy: %s\n", str1);// 测试重叠的情况my_memmove(str1, str1 + 2,12);        //这里复制 11个和复制12个是完全不一样的复制11个的时候会有一部分未被覆盖,当复制12个的时候虽然也有一部分未被覆盖但是把\0复制了过去,所以没有影响打印出来的结果// 打印重叠复制后的字符串printf("Overlapping copy: %s\n", str1);return 0;
}

下面就是复制了12个的结果 

三、memset函数的使用

函数原型:

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

头文件<string.h>

 ptr指向要填充的内存块的指针。可以是数组、结构体等任意类型的内存区域

value是要设置的值。虽然参数类型时int,但实际上只有低8位会被使用,因此可以把它看作是一个unsigned char类型的值。 

num是要填充的字节数。这决定了从ptr所指向的地址开始,有多少个字节会被设置位value

#include <stdio.h>
#include <string.h>
int main() {int arr[10] = { 0 };memset(arr,1, 4);printf("%d ",arr[0]);return 0;
}

 肯定有人会认为打印出来的结果是1,其实不然

arr[0]在内存中存放为0x00 00 00 00,

因为num被设置为是4,所以每个字节都被设置为01,,此时它的在内存中存放为0x01 01 01 01。

换算为十进制位结果是16843009

如果想设置为1,则可以将num改为1.

四、memcmp函数的使用

函数原型:

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

头文件<string.h>

 memcmp函数能将ptr1和ptr2指向的内存块前num个字节进行比较,比较后会返回一个值,具体结果如下

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

arr1和arr2比较前24个字节后返回的结果是-1。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot项目打包成war包

1、首先创建一个springboot工程&#xff0c;然后我们改造启动类如&#xff1a; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuil…

【大模型基础_毛玉仁】3.3 思维链

目录 3.3 思维链3.3.1 思维链提示的定义3.3.2 按部就班1&#xff09;Zero-Shot CoT2&#xff09;Auto-CoT 3.3.3 三思后行1&#xff09;思维树&#xff08;Tree of Thoughts, ToT&#xff09;2&#xff09;思维图&#xff08;Graph of Thoughts, GoT&#xff09; 3.3.4 集思广益…

虚拟电商-延迟任务系统的微服务改造(二)

一、微服务注册中心Consul 编写完延迟任务系统的web层接口&#xff0c;也就是说可以基于http协议来访问延迟系统&#xff0c;接下来要将延迟任务改造成一个服务。首要考虑的问题就是服务的注册与发现&#xff0c;服务的注册与发现都离不开服务的注册中心&#xff0c;本项目选取…

场景题:如何设计一个抢红包随机算法

面试官&#xff1a;咱来写个算法题吧 设计一个抢红包的随机算法&#xff0c;比如一个人在群里发了100块钱的红包&#xff0c;群里有10个人一起来抢红包&#xff0c;每人抢到的金额随机分配。 1.所有人抢到的金额之和要等于红包金额&#xff0c;不能多也不能少。 2.每个人至少抢…

Java开发经验——Throwable/Exception异常处理方式

摘要 文章主要探讨了 Java 开发中 Throwable 和 Exception 的异常处理方式。阿里巴巴 Java 开发手册规定&#xff0c;RPC 调用、二方包、动态代理类等场景推荐使用 Throwable&#xff0c;因为这些场景可能会出现类似 NoClassDefFoundError 这样的严重错误&#xff0c;使用 Thr…

[Mysql]创建数据库基础

数据库意义 更加利于管理的东西-数据库&#xff0c;他能有效的管理数据 举例一个生活化的案例说明 如果说&#xff0c;图书馆是保存书籍的&#xff0c;那么数据库技术保存数据的 数据库的简单原理图 Mysql数据库三层结构与本质 数据库管理系统与 mysqld&#xff1a;MySQL 数…

AMBA-CHI协议详解(二十五)

AMBA-CHI协议详解&#xff08;一&#xff09;- Introduction AMBA-CHI协议详解&#xff08;二&#xff09;- Channel fields / Read transactions AMBA-CHI协议详解&#xff08;三&#xff09;- Write transactions AMBA-CHI协议详解&#xff08;四&#xff09;- Other transac…

【RabbitMQ】RabbitMQ的基本架构是什么?包括哪些核心组件?

RabbitMQ基于AMQP协议实现&#xff0c;由多个核心组件组成&#xff0c;确保消息的可靠传递。 Rabbit的架构图&#xff1a; 1.RabbitMQ的基本架构&#xff1a; 1.核心组件&#xff1a; 1.Producer(生产者)&#xff1a; 发送消息到RabbitMQ。 2.Exchange(交换机)&#xff1a;接…

【PCB工艺】基础:电子元器件

电子原理图&#xff08;Schematic Diagram&#xff09;是电路设计的基础&#xff0c;理解电子元器件和集成电路&#xff08;IC&#xff09;的作用&#xff0c;是画好原理图的关键。 本专栏将系统讲解 电子元器件分类、常见 IC、电路设计技巧&#xff0c;帮助你快速掌握电子电路…

Html label标签中的for属性(关联表单控件:将标签与特定的表单元素(如输入框、复选框等)关联起来;提高可用性;无障碍性)

文章目录 示例代码for属性含义完整代码示例 示例代码 <div class"form-group"> <!-- 表单组&#xff0c;包含省份输入框和标签 --><label for"province">省份名称&#xff1a;</label> <!-- 省份输入框的标签 --><input…

S32K144外设实验(二):ADC单通道单次采样(软件触发)

文章目录 1. 概述1.1 理论回顾1.1.1 时钟系统1.1.2 采样通道1.2 实验目的2. 配置与代码编写1. 概述 1.1 理论回顾 S32K144的ADC应该说是特别灵活,笔者采用循序渐进的方式来学习使用这个很重要的外设。 在《入门笔记系列》专栏中对用户手册进行了翻译和解读,这里在回顾一下A…

进程控制~

一.进程控制 1.进程创建 我们可以通过./cmd来运行我们的程序&#xff0c;而我们运行的程序就是bash进程常见的子进程。当然我们也可以通过fork()系统调用来创建进程。 NAME fork - create a child process SYNOPSIS #include <unistd.h> pid_t fork(void…

经历过的IDEA+Maven+JDK一些困惑

注意事项&#xff1a;由于使用过程中是IDEA绑定好另外2个工具&#xff0c;所以报错统一都显示在控制台&#xff0c;但要思考和分辨到底是IDEA本身问题导致的报错&#xff0c;还是maven导致的 标准配置 maven Java Compiler Structure 编辑期 定义&#xff1a;指的是从open pr…

将bin文件烧录到STM32

将bin文件烧录到STM32 CoFlash下载生成hex文件hex2bin使用下载bin到单片机 CoFlash下载 选择需要安装的目录 在Config中可以选择目标芯片的类型 我演示的是 stm32f103c8t6 最小系统板 Adapter&#xff1a;烧录器类型 Max Clock&#xff1a;下载速度 Por&#xff1a;接口类型&am…

硬件基础(5):(2)二极管分类

文章目录 &#x1f4cc; 二极管的分类与详细介绍1. **整流二极管&#xff08;Rectifier Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;补充说明&#xff1a; 2. **快恢复二极管&#xff08;Fast Recovery Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;…

【MySQL】MySQL如何存储元数据?

目录 1.数据字典的作用 2. MySQL 8.0 之前的数据字典 3. MySQL 8.0 及之后的数据字典 4.MySQL 8 中的事务数据字典的特征 5.数据字典的序列化 6. .sdi文件的作用&#xff1a; 7..sdi的存储方式 在 MySQL 中&#xff0c;元数据&#xff08;Metadata&#xff09; 是描述数…

瑞萨RA系列使用JLink RTT Viewer输出调试信息

引言 还在用UART调试程序么?试试JLINK的RTT Viewer吧!不需占用UART端口、低资源暂用、实时性高延时微秒级,这么好的工具还有什么理由不用了! 目录 一、JLink RTT Viewer 简介 二、软件安装 三、工程应用 3.1 SEGGER_RTT驱动包 3.2 手搓宏定义APP_PRINT 3.3 使用APP_…

Ranger 鉴权

Apache Ranger 是一个用来在 Hadoop 平台上进行监控&#xff0c;启用服务&#xff0c;以及全方位数据安全访问管理的安全框架。 使用 ranger 后&#xff0c;会通过在 Ranger 侧配置权限代替在 Doris 中执行 Grant 语句授权。 Ranger 的安装和配置见下文&#xff1a;安装和配置 …

LabVIEW烟气速度场实时监测

本项目针对燃煤电站烟气流速实时监测需求&#xff0c;探讨了静电传感器结构与速度场超分辨率重建方法&#xff0c;结合LabVIEW多板卡同步采集与实时处理技术&#xff0c;开发出一个高效的烟气速度场实时监测系统。该系统能够在高温、高尘的复杂工况下稳定运行&#xff0c;提供高…

【系统架构设计师】操作系统 - 特殊操作系统 ③ ( 微内核操作系统 | 单体内核 操作系统 | 内核态 | 用户态 | 单体内核 与 微内核 对比 )

文章目录 一、微内核操作系统1、单体内核 操作系统2、微内核操作系统 引入3、微内核操作系统 概念4、微内核操作系统 案例 二、单体内核 与 微内核 对比1、功能对比2、单体内核 优缺点3、微内核 优缺点 一、微内核操作系统 1、单体内核 操作系统 单体内核 操作系统 工作状态 : …