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

【C语言基础】:内存操作函数

文章目录

      • 一、memcpy函数的使用和模拟实现
        • 1.1 memcpy函数的使用
        • 1.2 memcpy函数的模拟实现
      • 二、memmove函数的使用和模拟实现
        • 2.1 memmove函数的使用
        • 2.2 memmove函数的模拟实现
      • 三、memset函数的使用
        • 3.1 menset函数的使用
      • 四、memcmp函数的使用
        • 4.1 memcmp函数的使用

在这里插入图片描述
                                                 学海无涯苦作海
创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~

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

函数原型

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

内存复制块

  1. 将num字节的值从源指向的位置直接复制到目标指向的内存块。
  2. 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本。
  3. 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节。
  4. 为了避免溢出,目标参数和源参数所指向的数组的大小应该至少为num字节,并且不应该重叠(对于重叠的内存块,memmove是一种更安全的方法)。
1.1 memcpy函数的使用

【示例】:将arr1中的前5个元素拷贝到arr2中

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

在这里插入图片描述

1.2 memcpy函数的模拟实现

模拟思路

函数参数和返回类型mencpy不仅可以将拷贝整形数据,其他的数据类型也可以拷贝,即参数类型根据传入的数据类型决定,需要接受任意类型的地址,所以参数类型可以定义成void*,因为src是原数据,我们不期望它被修改,所以要加const进行修饰;还需要指定拷贝num字节的值,即num要为非负数,为了避免传入进来的num是一个负数,可以将num定为size_t类型,memcpy返回的是目标空间的起始地址,即返回类型我们也定为void* 。
函数体:首先用assert断言判断传入进来的是否为空指针;void* 类型的指针不可以直接解引用,这里的num是指字节数,不同的数据类型所占的字节数不同,所以最好一个一个字节访问,即将 void* 强转成 char* (解引用时一次访问一个字节)类型;每访问一个字节后就自增一,拷贝完成后,这时的dest已经不再指向首元素地址,所以在这之前要创建一个void* 的指针记录dest,最后返回记录dest的指针即可。

模拟代码

#include<stdio.h>
#include<assert.h>void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;src = (char*)src + 1;dest = (char*)dest + 1;}return ret;
}int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };my_memcpy(arr2, arr1, 20);for (int i = 0; i < 20; i++){printf("%d ", arr2[i]);}return 0;
}

在这里插入图片描述
注意memcpy函数不可以拷贝重叠的内存块(虽然也能实现)但不安全,对于重叠的内存块,memmove是一种更安全的方法。

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

函数原型

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

移动内存块

  1. 将num字节的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,从而允许目标和源重叠。
  2. 源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本。
  3. 该函数不检查源中是否有任何终止null字符——它总是精确地复制num个字节。
  4. 为了避免溢出,目的参数和源参数所指向的数组的大小至少为num字节。

memcpymemmove的区别就在于memmove可以复制重叠的内存块

2.1 memmove函数的使用

【示例】:将arr1中的1,2,3,4,5这几个元素拷贝到arr1中的3,4,5,6,7的位置。

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

在这里插入图片描述

2.2 memmove函数的模拟实现

在这里插入图片描述

模拟思路

函数参数和返回类型:和memcpy函数一致,这里就不多作介绍了。
函数体:这里总体要分两种情况:一种是dest<src,另一种就是dest>src;对于第一种情况,需要从前向后拷贝,对于第二种情况,需要从后向前拷贝,至于不重叠的话,无论是从前向后还是从后向前都是可以的。从前向后拷贝的方法和memcpy是一致的,这里就不多说了;从后向前拷贝也比较简单,src强转成 char* 之后加上num就是最后一个字节,然后num不断自减,就可以实现从后向前拷贝。

模拟代码

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest < src){// 前-->后while (num--){*(char*)dest = *(char*)src;src = (char*)src + 1;dest = (char*)dest + 1;}}else {// 后-->前while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;
}int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr1 + 2, arr1, 5 * sizeof(int));for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

在这里插入图片描述

三、memset函数的使用

函数原型

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

填充内存块
将ptr指向的内存块的前num个字节设置为指定的值(解释为unsigned char)。
参数说明
ptr
指向要填充的内存块的指针。
value
需要设置的值。该值作为int类型传递,但函数使用该值的unsigned char转换来填充内存块。
num
要设置为该值的字节数。size_t是一个无符号整型。

3.1 menset函数的使用

【示例】:将arr数组中的hello替换成x

#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);return 0;
}

在这里插入图片描述
注意:这里的num指的是该值的字节数

四、memcmp函数的使用

函数原型

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

比较两个内存块
将ptr1所指向的内存块的前num字节与ptr2所指向的前num字节进行比较,如果它们都匹配则返回0,如果不匹配则返回不同于0的值,表示哪个值更大。
参数说明
ptr1
指向内存块的指针。
ptr2
指向内存块的指针。
num
要比较的字节数。
注意:与strcmp不同,该函数在找到空字符后不会停止比较。

return value(返回值)indicates(含义)
<0在两个内存块中不匹配的第一个字节在ptr1中的值低于ptr2中的值(如果作为unsigned char值计算)
0两个内存块的内容是相等的
.>0在两个内存块中不匹配的第一个字节在ptr1中的值大于ptr2中的值(如果作为unsigned char值计算)
4.1 memcmp函数的使用

【示例】:比较arr1数组和arr2数组中前16个字节;在比较前17个字节。

#include<stdio.h>
#include<string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7 };int arr2[] = { 1,2,3,4,8,8,8 };int ret1 = memcmp(arr1, arr2, 16);int ret2 = memcmp(arr1, arr2, 17);printf("%d\n", ret1);printf("%d\n", ret2);return 0;
}

在这里插入图片描述
在这里插入图片描述

分析:一个整型占4个字节,比较前16个字节就是比较前4个元素,前4个元素都是一样的,所以返回0。但从17个字节开始,arr1和arr2数组就开始不同了,arr1是05,而arr2是08,08大于05,所以返回-1。

相关文章:

【C语言基础】:内存操作函数

文章目录 一、memcpy函数的使用和模拟实现1.1 memcpy函数的使用1.2 memcpy函数的模拟实现 二、memmove函数的使用和模拟实现2.1 memmove函数的使用2.2 memmove函数的模拟实现 三、memset函数的使用3.1 menset函数的使用 四、memcmp函数的使用4.1 memcmp函数的使用 学海无涯苦作…...

3.24作业

基于UDP的网络聊天室 项目需求&#xff1a; 如果有用户登录&#xff0c;其他用户可以收到这个人的登录信息如果有人发送信息&#xff0c;其他用户可以收到这个人的群聊信息如果有人下线&#xff0c;其他用户可以收到这个人的下线信息服务器可以发送系统信息 服务器端代码 #in…...

Excel双击单元格后弹窗输入日期

Step1. 在VBE界面新建一个窗体(Userform1),在窗体的工具箱的空白处右键,选中添加附件,勾选Calendar control 8.0,即可完成日历的添加。 PS:遗憾的是, Office 64 位没有官方的日期选择器控件。唯一的解决方案是使用Excel 的第三方日历。 参考链接:How to insert calen…...

原生 HTML/CSS/JS 实现右键菜单和二级菜单

文章来源&#xff1a;www.huhailong.vip 站点 文章源地址&#xff1a;https://www.huhailong.vip/article/1764653112011841538 Demo效果演示地址 先看效果图 {{{width“auto” height“auto”}}} 需要注意的就是边界检测处理&#xff0c;到极端点击底部和右侧时如果不做处理会…...

[项目前置]如何用webbench进行压力测试

测试软件 采用webbench进行服务器性能测试。 Webbench是知名的网站压力测试工具&#xff0c;它是由Lionbridge公司开发。 webbench的标准测试可以向我们展示服务器的两项内容&#xff1a; 每秒钟相应请求数 和 每秒钟传输数据量 webbench测试原理是&#xff0c;创建指定数…...

网络七层模型:理解网络通信的架构(〇)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

format(C++20)

1. std::format format_01.cpp // g format_01.cpp -stdc20 #include <iostream> #include <string> #include <format>void test_01() {// 使用字符串填充std::cout << std::format("Hello {}!\n", "World"); // Hello World!…...

Ftrans安全数据摆渡系统 构建便捷的内外网数据交换通道

安全数据摆渡系统是一种设计用于解决内外网环境下&#xff0c;数据传输、管理、共享问题的安全系统&#xff0c;通过加密、访问控制等策略&#xff0c;提供安全可靠的数据传输和共享服务&#xff0c;尤其适用于对网络安全建设要求高的行业&#xff0c;比如研发型企业、党政机构…...

【云开发笔记No.14】持续交付、持续部署、持续交付流水线

一、持续交付 持续交付&#xff08;Continuous Delivery&#xff09;是一种软件开发方法论&#xff0c;它强调在开发过程中&#xff0c;软件可以在任何时间以最小的努力被部署到生产环境。其核心是确保代码更改在经过一系列自动化测试后&#xff0c;能够快速、安全地集成到主代…...

蓝桥杯练习07小兔子爬楼梯

小兔子爬楼梯 介绍 小兔子想去月球上旅行&#xff0c;假设小兔子拥有一个阶梯子&#xff0c;当你爬完层就可以到达月球&#xff0c;小兔子每次可以跳1或者2个台阶&#xff0c;小兔子有多少种跳法可以到达月球呢&#xff1f; 给定n是一个正整数&#xff0c;代表梯子的阶数&…...

Docker in Docker原理与实战

Docker in Docker (DinD) 是一种在Docker容器内部运行Docker的技术。它允许在一个Docker容器内部创建和管理其他的Docker容器&#xff0c;实现了一个容器内部的容器编排环境。本文将介绍Docker in Docker的原理&#xff0c;并给出一个实际的应用场景。 Docker in Docker的原理…...

Ruoyi若依框架下载流程详细解读(SpringBoot-Vue)

图解&#xff1a; 前端设计&#xff1a; 前端设计一个link文字连接或者按钮&#xff08;ElementUI&#xff09;Element - The worlds most popular Vue UI framework 前端请求设计&#xff1a; import request from /utils/request //下载示例模型定义语言的JSON export const…...

【深度学习】Pytorch中实现交叉熵损失计算的方式总结

在PyTorch中&#xff0c;计算交叉熵损失主要有以下几种方式&#xff0c;它们针对不同的场景和需求有不同的实现方式和适用范围&#xff1a; 1. nn.CrossEntropyLoss 类 这是最常用且方便的方法&#xff0c;特别适用于多分类任务。nn.CrossEntropyLoss 实际上是同时完成了 sof…...

机器学习:处理jira工单的分类问题

如何根据jira工单的category、reporter自动找到处理它的组呢?这是一个利用机器学习中knn算法的小实践. 目录 Knn算法 数据 示例 分割数据 选择Neighbors knn的优缺点 机器学习是一种技术,它的目的是给机器学习能力,让它们可以根据数据自己做决定,所以对于训练…...

后端常问面经之操作系统

请简要描述线程与进程的关系,区别及优缺点&#xff1f; 本质区别&#xff1a;进程是操作系统资源分配的基本单位&#xff0c;而线程是任务调度和执行的基本单位 在开销方面&#xff1a;每个进程都有独立的代码和数据空间&#xff08;程序上下文&#xff09;&#xff0c;程序之…...

RK3568平台 iperf3测试网络性能

一.iperf3简介 iperf是一款开源的网络性能测试工具&#xff0c;主要用于测量TCP和UDP带宽性能。它可以在不同的操作系统上运行&#xff0c;包括Windows、Linux、macOS等。iperf具有简单易用、功能强大、高度可配置等特点&#xff0c;广泛应用于网络性能测试、网络故障诊断和网…...

Spring Boot中实现对特定URL的权限验证:拦截器、切面和安全框架的比较

引言&#xff1a; 在开发Web应用程序时&#xff0c;对特定URL进行权限验证是一项常见的需求。在Spring Boot中&#xff0c;我们有多种选择来实现这一目标&#xff0c;其中包括使用拦截器、切面和专门的安全框架&#xff08;如Spring Security&#xff09;。本文将比较这三种方式…...

【能源数据分析-00】能源领域数据集集锦(动态更新)

一、前言 大数据科学在能源领域的深度应用&#xff0c;已经深刻改变了这一行业的垂直格局。它为我们提供了宝贵的见解&#xff0c;帮助降低下游市场的成本&#xff0c;使石油生产商能够更好地应对市场繁荣期的需求。近期&#xff0c;石油价格的剧烈下跌给全球经济带来了沉重打…...

数据挖掘与机器学习 1. 绪论

于高山之巅&#xff0c;方见大河奔涌&#xff1b;于群峰之上&#xff0c;便觉长风浩荡 —— 24.3.24 一、数据挖掘和机器学习的定义 1.数据挖掘的狭义定义 背景&#xff1a;大数据时代——知识贫乏 数据挖掘的狭义定义&#xff1a; 数据挖掘就是从大量的、不完全的、有噪声的、…...

Matlab实现序贯变分模态分解(SVMD)

大家好&#xff0c;我是带我去滑雪&#xff01; 序贯变分模态分解(SVMD) 是一种信号处理和数据分析方法。它可以将复杂信号分解为一系列模态函数&#xff0c;每个模态函数代表信号中的特定频率分量。 SVMD 的主要目标是提取信号中的不同频率分量并将其重构为原始信号。SVMD的基…...

【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析

欢迎来到啾啾的博客&#x1f431;。 记录学习点滴。分享工作思考和实用技巧&#xff0c;偶尔也分享一些杂谈&#x1f4ac;。 有很多很多不足的地方&#xff0c;欢迎评论交流&#xff0c;感谢您的阅读和评论&#x1f604;。 目录 引言Redisson基本信息Redisson网站 Redisson应用…...

获取 OpenAI API Key

你可以按照以下步骤来获取 openai.api_key&#xff0c;用于调用 OpenAI 的 GPT-4、DALLE、Whisper 等 API 服务&#xff1a; &#x1f9ed; 获取 OpenAI API Key 的步骤&#xff1a; ✅ 1. 注册或登录 OpenAI 账号 打开 https://platform.openai.com/ 使用你的邮箱或 Google/…...

学习路之php--性能优化

一、php周边优化 二、代码级优化 变量管理‌ 及时unset()释放大数组/对象&#xff0c;减少内存占用局部变量访问速度比全局变量快约2倍&#xff0c;优先使用局部变量大数组采用引用传递&#xff08;&$var&#xff09;避免内存 循环优化‌ 预计算循环次数&#xff1a; …...

任务调度器-关于中心化调度 vs 去中心化调度的核心区别

1. 定义与架构模型 维度中心化调度去中心化调度核心角色存在一个中央调度器&#xff08;如XXL-JOB的调度中心&#xff09;&#xff0c;统一管理任务分配、状态监控和故障处理。无中心节点&#xff0c;调度逻辑分散在多个节点&#xff0c;通过共识算法&#xff08;如选举机制&a…...

My图床项目

引言: 在海量文件存储中尤其是小文件我们通常会用上fastdfs对数据进行高效存储,在现实生产中fastdfs通常用于图片,文档,音频等中小文件。 一.项目中用到的基础组件(Base) 1.网络库(muduo) 我们就以muduo网络库为例子讲解IO多路复用和reactor网络模型 1.1 IO多路复用 我们可以…...

html文字红色粗体,闪烁渐变动画效果,中英文切换版本

1. 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>红色粗体闪烁文字表格 - 中英文切换</t…...

数据库SQLite基础

SQLite的存储结构 --->B树 大型数据库 &#xff1a;Oracle 中型数据库 &#xff1a;Server是微软开发的数据库产品&#xff0c;主要支持windows平台 小型数据库 : MySQL是一个小型关系型数据库管理系统。开放源码 (嵌入式不需要存储太多数据) 一、SQLite基础 SQLite的源代码…...

npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupported

npm run dev时报错如下 原因&#xff1a;更换node版本导致 解决&#xff1a; 修改package.json文件&#xff0c;在相关构建命令之前加入 SET NODE_OPTIONS–openssl-legacy-provider 运行成功...

# 从底层架构到应用实践:为何部分大模型在越狱攻击下失守?

从底层架构到应用实践&#xff1a;为何部分大模型在越狱攻击下失守&#xff1f; 引言 近期&#xff0c;我们对多个主流大语言模型&#xff08;LLM&#xff09;进行了安全性测试&#xff0c;使用了极具诱导性的越狱提示词&#xff0c;试图绕过其内容安全机制。测试结果显示&am…...

基于PSO粒子群优化的VMD-GRU时间序列预测算法matlab仿真

目录 1.前言 2.算法运行效果图预览 3.算法运行软件版本 4.部分核心程序 5.算法仿真参数 6.算法理论概述 6.1变分模态分解&#xff08;VMD&#xff09; 6.2 门控循环单元&#xff08;GRU&#xff09; 6.3 粒子群优化&#xff08;PSO&#xff09; 7.参考文献 8.算法完…...