c语言回顾-内存操作函数

目录

前言

1.memcpy 函数

1.1函数介绍

1.2与strcpy的区别

1.3memcpy的模拟

2.memmove 函数

2.1函数介绍和使用

2.2函数的模拟

3.memset函数

3.1函数介绍

3.2函数的模拟

4.memcmp函数

4.1函数的使用

4.2函数的模拟

结束语


前言

在动态内存的章节中小编详细讲解了动态内存分配函数,在这里小编将补充内存操作函数的讲解!

1.memcpy 函数

1.1函数介绍

原型:void *memcpy(void *dest, const void *src, size_t n);

功能:将 n 字节的数据从源内存区域 src 复制到目标内存区域 dest

  • 参数:
    • dest:指向目标内存区域的指针。
    • src:指向源内存区域的指针。
    • n:要复制的字节数。
  • 返回值:返回指向目标内存区域的指针。
char src[10] = "Hello";
char dest[10];
memcpy(dest, src, 5); // 将前5个字节从 src 复制到 dest

又比如将数组中的指定的数据放到另一个数组中

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

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

1.2与strcpy的区别

  1. 数据类型

    • memcpy:适用于任意类型的数据,复制的是指定的字节数。
    • strcpy:仅适用于字符串,复制的是字符,直到遇到空字符为止。
  2. 复制内容

    • memcpy:不会检查内容,只复制指定字节数,即使其中包含空字符。
    • strcpy:遇到空字符时停止复制,并将空字符包含在内。
  3. 使用场景

    • memcpy:适用于需要复制特定大小内存块的场景,例如结构体、数组等。
    • strcpy:适用于字符串复制的场景,确保字符串以空字符结尾。
  4. 安全性

    • memcpy:需要手动管理字符串结尾,容易出现内存越界问题。
    • strcpy:自动处理字符串结尾,但在源字符串未包含空字符时容易造成缓冲区溢出。

注意:如果source和destination有任何的重叠,复制的结果都是未定义的。但是vs,vscode 等运行出来的结果却是对的,或许提升了性能。

1.3memcpy的模拟

因为我们不知道所要复制的数据类型是什么,所以参数类型我们设置为void*,接受各种类型,

用因为void*不能解应用,所以强制转化类型操作,强制转化为char*

#include <stdio.h>
void*my_memcpy(void*dest,const void*src,size_t count)
{void*ret=dest;while(count--){*(char*)dest=*(char*)src;//强制转化类型dest=(char*)dest+1;src=(char*)src+1;}return ret;
}
int main()
{
int arr1[10]={0};
int arr2[10]={1,2,3,4,5,6,7,8,9,10};
my_memcpy(arr1, arr2,20); //5个整型复制占20个字节
for(int i=0;i<10;i++)
{printf("%d ",arr1[i]);
}
return 0;
}

运行结果:

在 my_memcpy 函数中使用

*(char*)dest = *(char*)src ;dest = (char*)dest + 1;src = (char*)src + 1

是因为我们希望逐字节复制数据。使用 char 类型指针可以确保每次操作都是一个字节,这对于实现 memcpy 函数的逐字节复制行为是必要的。 

为什么使用 `char`

逐字节复制:char 类型指针每次移动一个字节,这是我们想要的行为,因为 memcpy 需要逐字节复制数据。

通用性:char类型适用于任何类型的数据,无论是整数、浮点数还是结构体,因为它操作的是最小单位的字节。

如果使用 int或double其他类型指针,则会面临对齐问题和类型限制,无法实现 memcpy函数的通用性。

2.memmove 函数

2.1函数介绍和使用

void * memmove ( void * destination, const void * source, size_t num );
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
使用:
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10]={1,2,3,4,5,6,7,8,9,10};
memmove(arr1+3, arr1,20); 
for(int i=0;i<10;i++)
{printf("%d ",arr1[i]);
}
return 0;
}

运行结果:

2.2函数的模拟

#include <stdio.h>
#include <string.h>
void *my_memmove(void *dest, const void *src, size_t n)
{char *csrc = (char *)src;char *cdest = (char *)dest;if(csrc<cdest){for(int i=n-1;i>=0;i--){cdest[i]=csrc[i];}}else{for(int i=0;i<n;i++){cdest[i]=csrc[i];}}return dest;
}
int main()
{
int arr1[10]={1,2,3,4,5,6,7,8,9,10};
my_memmove(arr1, arr1+4,20); 
for(int i=0;i<10;i++)
{printf("%d ",arr1[i]);
}
return 0;
}

my_memove(arr1+4,arr1,20)时

画图解释:

3.memset函数

3.1函数介绍

void * memset ( void * ptr, int value, size_t num );
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。 函数用于将指定的值设置到一段内存区域中。它在初始化数组或结构体时非常有用。
#include <stdio.h>
#include <string.h>
int main ()
{char str[] = "hello world";memset (str+2,'x',6);printf(str);return 0;
}

输出结果:hexxxxxxrld

3.2函数的模拟

#include <stdio.h>
#include <string.h>
void*my_memset(void*dest, int c, size_t count)
{char*str = (char*)dest;while(count--){*str++ = (char)c;}return dest;
}
int main ()
{char str[] = "hello world";my_memset (str+2,'x',6);printf("%s\n", str);int arr[10]={1,2,3,4,5,6,7,8,9,10};my_memset(arr,0,20);
for(int i=0;i<10;i++)
{printf("%d ",arr[i]);
}return 0;
}

4.memcmp函数

4.1函数的使用

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
#include <stdio.h>
#include <string.h>
int main()
{char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n;n = memcmp(buffer1, buffer2,sizeof(buffer1));if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);elseprintf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;
}

4.2函数的模拟

#include <stdio.h>
#include <string.h>
int my_memcmp(const void *str1, const void *str2, size_t n)
{const unsigned char *s1 = (const unsigned char *)str1;const unsigned char *s2 = (const unsigned char *)str2;/*size_t i;for (i = 0; i < n; i++){if (s1[i] < s2[i])return -1;if (s1[i] > s2[i])return 1;}return 0;*/while (n--){if (*s1 != *s2)return (*s1 - *s2);s1++;s2++;}return 0;
}int main()
{int a[6]={1,2,3,4,5,6};int b[6]={1,2,3,4,5,7};int n;n = my_memcmp(a,b,20);if (n > 0)printf("Array 'a' is greater than array 'b'.\n");
else if (n < 0)printf("Array 'a' is less than array 'b'.\n");
elseprintf("Array 'a' is the same as array 'b'.\n");return 0;
}

比较前五个数数据:

结束语

OK啦,本节的干货也彻底上完了,相信大家多内存函数有了进一步的认识,

最后友友们动动你们尊贵的手指给小编点点赞,评论一下吧,忠诚感谢大家的支持!!!

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

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

相关文章

代码随想录算法训练营第69天:图论7[1]

代码随想录算法训练营第69天&#xff1a;图论7 109. 冗余连接II 卡码网题目链接&#xff08;ACM模式&#xff09;(opens new window) 题目描述 有向树指满足以下条件的有向图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节…

C++多进程下使用文件锁互斥执行压缩进程

文章目录 0. 引言1. 解决方案2. 文件锁相比信号量的优势3. 示例代码compress_log.cpp4. 流程图5. 总结 0. 引言 在多进程环境中&#xff0c;每个进程都会生成自己的日志文件&#xff0c;并独立进行gzip压缩。尽管每个进程压缩的频率和时间可能不同&#xff0c;但由于系统的运行…

【Arduino】ESP8266开发环境配置(图文)

ESP8266与ESP32开发很类似&#xff0c;相当于是低配版本的ESP32&#xff0c;其同样具有无线网络连接能力&#xff0c;功能强大&#xff0c;而且价格比ESP32更具有优势。接下来我们就来设置一下ESP8266的开发环境。 使用Arduino开发平台软件&#xff0c;选择首选项进行设置。 h…

ASP.NET Core 6.0 使用 Action过滤器

Action过滤器 在ASP.NET Core中&#xff0c;Action过滤器用于在执行Action方法之前或之后执行逻辑。你可以创建自定义的Action过滤器来实现这一点。 继承 ActionFilterAttribute 类&#xff1a; [TypeFilter(typeof(CustomAllActionResultFilterAttribute))]public IActionRe…

67.WEB渗透测试-信息收集- WAF、框架组件识别(7)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;66.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;6&#xff09;-CSDN博客 关于w…

【大模型】MOE模型混合专家调度机制详解

MOE模型混合专家调度机制详解 引言 在大规模机器学习和深度学习应用中&#xff0c;模型的复杂性和计算需求日益增长。为了解决单个专家模型在特定任务上的局限性&#xff0c;Mixture of Experts (MoE) 架构应运而生。MoE模型通过组合多个专家模型&#xff0c;能够在保持高效率…

第四届数字安全大会:AI时代数据安全策略与天空卫士创新实践

2024年6月22日&#xff0c;以 “新质•真能力”为主题的第四届数字安全大会在北京隆重召开。这场由数世咨询和CIO时代联合主办的行业盛会&#xff0c;集中探讨了大模型、数据治理与流通、以及安全运营等当前最前沿的议题。大会吸引了来自不同行业的首席信息官&#xff08;CIO&a…

2024Datawhale-AI夏令营——机器学习挑战赛——学习笔记

#ai夏令营#datawhale#夏令营 Day1:入门级demo运行 这个其实比较简单&#xff0c;按照操作来做就行了&#xff0c;特征工程和调参暂时都没有做&#xff0c;后续的才是重头戏。 Day2:正式比赛开始 赛题&#xff1a;数据挖掘赛道——利用机器学习方法根据给定的特征判断PROTACs…

【EFK】efk 8收集docker容器日志测试

前言 目前&#xff0c;efk 全家桶已经更新到版本8 了&#xff0c;本章节我们使用8版本的elk搭建日志收集系统&#xff0c;了解它的配置运行过程&#xff0c;方便以后在更复杂的环境中更好的使用。 版本默认就是8最新的&#xff0c;也可以自己指定其他8的版本 elasticsearch: …

左耳听风_008_07_推荐阅读每个程序员都该知道的知识

你好&#xff0c;我是陈浩网名左耳朵耗子。 在整个为期一年的专栏内容中啊&#xff0c;我会一步步向你推荐一些有价值的内容供你参考。 这些内容有中文&#xff0c;有英文&#xff0c;也有视频。 他们都是我认为对我非常有价值的信息&#xff0c;我也希望他们能够对你有同样…

vs 远程链接ssh 开发 简单实验

1.概要 动态编译语言&#xff0c;跨平台必须做分别的编译&#xff0c;比如linux和windows。如何再windows环境下开发编译出linux平台的程序呢&#xff0c;vs支持远程链接编辑&#xff0c;就是再vs中写代码&#xff0c;但是编译确是链接远程的环境编译的。 2.环境准备 2.1 vs…

R语言学习,入门

我是一名6年开发经验的程序员&#xff0c;后端&#xff0c;大数据&#xff0c;前端都会。 现在加入了医疗行业&#xff0c;要做数据分析&#xff0c;前同事的实验室生信专业的&#xff0c;用的是R语言&#xff0c;为了跑通他的程序。就来学一下吧&#xff0c;看了一下好像挺简…

代码随想录day38 动态规划(4)

1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 难点在于将此问题转为0-1背包问题。思路是将石头分为重量尽可能接近的两堆&#xff0c;两堆之间对碰&#xff0c;到最后剩下的重量会最小。解法与分割等和子集类似。易错点是遍历target时从后往前。 cl…

关于软件本地化,您应该了解什么?

软件本地化是调整软件应用程序以满足目标市场的语言、文化和技术要求的过程。它不仅仅涉及翻译用户界面&#xff1b;它包含一系列活动&#xff0c;以确保软件在目标语言环境中可用且相关。以下是您应该了解的有关软件本地化的一些关键方面&#xff1a; 了解范围 软件本地化是…

0704模拟记录

1.完美数 暴力 #include <iostream> #include <vector>using namespace std;bool perfect(long long res) {if (res < 10) {return true;}else if (res > 10 && res < 100 && res % 10 0) {return true;}else if (res > 100 &&…

华为机试HJ12字符串反转

华为机试HJ12字符串反转 题目&#xff1a; 接受一个只包含小写字母的字符串&#xff0c;然后输出该字符串反转后的字符串。&#xff08;字符串长度不超过1000&#xff09; 想法&#xff1a; 针对输入字符串从后往前遍历&#xff0c;输出反转字符串 input_str input()resu…

requets.GET.get()怎样使用?

request.GET.get()是Django中用于获取GET请求参数的方法。 使用方法如下&#xff1a; 在视图函数中引入HttpRequest模块&#xff1a;from django.http import HttpRequest在视图函数中使用request.GET.get()方法获取GET请求参数&#xff0c;参数为需要获取的参数名 def my_…

水利水电安全员C证考试题库资料,2024年全国考试通用!

1.安全生产民事责任&#xff0c;是指责任主体违反安全生产法律规定造成&#xff08;&#xff09;&#xff0c;由人民法院依照民事法律强制其行使民事赔偿的一种法律责任。民事责任追究的目的是为了最大限度的维护当事人受到民事损害时享有获得民事赔偿的权利。 A.民事损伤 B.…

针对SVN、GIT版本管理工具进行源代码加密保护

针对SVN、GIT版本管理工具进行源代码加密保护 在软件开发过程中&#xff0c;版本管理工具如SVN和GIT是不可或缺的组成部分&#xff0c;它们帮助团队管理源代码的变更和版本。然而&#xff0c;这些工具也面临着源代码泄露的安全风险。如果不针对数据进行加密保护&#xff0c;很…

如何从腾讯云迁移到AWS

随着跨境出海潮不断扩大&#xff0c;企业越来越意识到将工作负载迁移到海外节点的必要性&#xff0c;以获取更多功能、灵活性和性能。然而&#xff0c;顺利迁移业务主机并确保业务稳定访问是一项具有挑战性的任务。在此挑战中&#xff0c;借助AWS迁移工具和迁移流程的强大支持&…