C语言内存函数的使用、剖析及模拟实现

目录

一、内存拷贝函数——memcpy

1.函数声明:

注意:

2.函数使用用例:

3.memcpy函数的模拟实现:

二、内存拷贝函数2——memmove

1.函数声明:

2.memmove函数的模拟实现

三、内存比较函数——memcmp

1.函数声明:

2.函数使用实例:

四、内存设置函数——memset

1.函数声明:

2,函数使用实例:


一、内存拷贝函数——memcpy

1.函数声明:

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

解释:

①:作用:将source所指向的空间的内容的前num个字节的内容拷贝到destination指向的空间。

②:该函数有三个参数:

第一个参数是个void*的指针,指向目的地空间;

第二个参数是个void*的指针,用于指向源头空间;

第三个参数类型为size_t,代表待拷贝的字节数。

③:该函数的返回类型为void*,即目标空间destination的起始地址。

④:该函数包含在头文件<string.h>中。

注意:

1.想到“拷贝”两个字,很多贴子可能会想到“strcpy”,但一定要注意,“strcpy”函数只能用于字符串拷贝,而“memcpy”函数可能拷贝不同类型的数据(int*、char*、...等等),所以我们还可以看到,该函数的形参的两个指针都是void*型,就是为了接收不同类型的数据。

2.memcpy函数只能用于处理不重叠的内存的拷贝(如将数组下标为1,2,3,4,5的内容拷贝到该数组下标为3,4,5,6,7的位置,这种情况下标为3,4,5的内存空间就是重叠了),否则会产生错误。重叠内存的拷贝由另外一个函数——memmove来实现,介绍在下文。

2.函数使用用例:

#include<stdio.h>
#include<string.h>
int main()
{//**********用例1***************************int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };int arr2[10] = { 0 };memcpy(arr2, arr1, sizeof(arr1));printf("arr2:");for (int i = 0; i < 10; i++){printf("%d ", arr2[i]);}printf("\n");//**********用例2****************************float arr3[5] = { 1.0,2.0,3.0,4.0,5.0 };float arr4[5] = { 0 };printf("arr4 ");memcpy(arr4, arr3, sizeof(arr3));for (int i = 0; i < 5; i++){printf("%f ", arr4[i]);}return 0;
}

用例运行结果:

3.memcpy函数的模拟实现:

①:源代码

//函数模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>void* my_memcpy(void* dest, void* sour, size_t size)
{void* ret = dest;assert(dest && sour);while (size--){*(char*)dest = *(char*)sour;dest = (char*)dest + 1;sour = (char*)sour + 1;}return ret;
}
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 0 };my_memcpy(arr2, arr1, sizeof(arr1));for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

解释:

①:因为是模拟实现,所以返回类型和参数类型都要相同。

②:因为返回值为目标空间的起始地址,所以开始先创建一个void*的指针将目标空间的起始地址dest保存起来。

②:因为void*指针不能用于加减和解引用操作,所以必须强制转换为其他类型的指针,所以就要思考转化为什么类型?因为是以字节为单位,所以很显然转为化char*指针就可以一字节一字节的拷贝。所谓拷贝无非就是赋值操作。

③:我们知道是以字节为单位进行拷贝,所以循环次数即为待拷贝字节数size,所以用一个while循环即可,循环体里面就是拷贝部分,先将两个指针转化为char*的指针,这样解引用的访问权限就是一个字节,这样依次赋值下去,最后在返回目标空间的起始地址ret即可。

二、内存拷贝函数2——memmove

1.函数声明:

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

解释:

①:我们发现该函数的返回类型及参数类型和“memcpy”函数都是一样的,不难理解,因为两者都是内存的拷贝,只是“memmove”函数有一点更高级的功能,就是可以对重叠的内存进行拷贝。

2.memmove函数的模拟实现

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

运行结果:

三、内存比较函数——memcmp

1.函数声明:

  

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

解释:

①:该函数的作用就是将ptr1所指向的内容和ptr2所指向的内容进行比较,同样以字节为单位,但要注意的是,是以字节为单位进行比较,第三个参数num就是待比较字节数。

②:注意别和字符串比较函数“strcmp”混淆,“strcmp”只能用于字符串的比较,而此函数可以进行不同类型的数据的比较。

②:比较规则:(可参考函数“strcmp”)

若前大于后,返回一个大于0的数字;

若前等于后,返回0;

若前小于后,返回一个小于0的数字。

2.函数使用实例:

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,2,3,4,6 };printf("%d\n", memcmp(arr1, arr2, 20));return 0;
}

很明显,arr1前四个数和arr2相同,但第五个数比arr2的第五个数小,所以会的到一个小于0的数,vs编译器默认这个小于0的数为-1,大于0的数为1.

四、内存设置函数——memset

1.函数声明:

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

①:函数的作用就是将ptr所指向的空间的内容的前num个字节的内容设置成第二个参数的值value,一定要注意是以字节为单位,可参考使用实例。

②:返回值为ptr指向的空间的起始地址。

2,函数使用实例:

本次知识到此结束,希望对你有所帮助!

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

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

相关文章

ros2发布者节点

没有书看啊&#xff0c;就来看看这个代码吧&#xff1a; 首先&#xff1a;第一个函数&#xff1a;init&#xff0c;通过f12可以知道这个函数共有4个变量&#xff0c;前面2个就这么填&#xff0c;后面2个有默认值&#xff0c;不用管&#xff0c;所以一般这么写就好了。 spin函…

【数据分享】海洋热含量Global Ocean Heat Content CDR】

【数据分享】海洋热含量Global Ocean Heat Content CDR 海洋与大气科学 海洋热含量数据可以不用计算了&#xff0c;直接下载使用&#xff01; 海洋热含量气候数据记录&#xff08;CDR&#xff09;是一组 1955 年至今的海洋热含量异常&#xff08;OHCA&#xff09;时间序列&…

ChatGLM OPENCL 和 CUDA 哪个 GPU 加速计算框架更快

OpenCL和CUDA都是强大的GPU加速计算框架,CUDA在与NVIDIA GPU的紧密结合下提供了更高性能,适用于专注于NVIDIA平台开发者;而OpenCL具有跨平台兼容性和多厂商支持的优势,适用于需要在不同硬件平台上进行开发的场景。 在现代计算领域,GPU 加速已经成为一种强大的工具,能够显…

Python 基于人脸识别的实验室智能门禁系统的设计,附可视化界面

1 简介 本基于人脸识别的实验室智能门禁系统通过大数据和信息化的技术实现了门禁管理流程的信息化的管理操作。平台的前台页面通过简洁的平台页面设计和功能结构的分区更好的提高用户的使用体验&#xff0c;没有过多的多余的功能&#xff0c;把所有的功能操作都整合在功能操作…

Windows安装Mysql--免安装版

在Windows系统上安装免安装版MySql的步骤 官方下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 将下载好的文件“mysql-5.7.18-winx64”解压缩到C盘的 目录下&#xff1a; 配置环境变量&#xff1a; &#xff08;略&#xff09; 正式安装&#xff0c;添加my.i…

CSDN博客去水印方法

直接在 创作中心->博客 设置这里关了好像就行了&#xff0c;之前方法是找图片链接?后面的一大串字符给去掉。

Excel中的宏、VBA

一、宏是什么&#xff1f; EXCEL MACRO 是一种记录和播放工具&#xff0c;它仅记录您的 Excel 步骤&#xff0c;并且宏将根据需要播放任意多次。 VBA 宏可自动执行重复任务&#xff0c;从而节省了时间。 这是一段可在 Excel 环境中运行的编程代码&#xff0c;但您无需成为编码…

C语言大佬的必杀技---宏的高级用法

C语言大佬的必杀技—宏的高级用法 目录: 字符串化标记的拼接宏的嵌套替换多条语句防止一个文件被重复包含宏和函数的区别 可能大家在学习的时候用得比较少&#xff0c;但是在一些代码量比较大的时候&#xff0c;这样使用&#xff0c;可以大大的提高代码的可读性&#xff0c;…

SpringBoot轻松实现项目集成Knife4j接口文档

Knife4j 介绍 Knife4j 官网 Knife4j是一款基于Swagger生成API文档的增强工具&#xff0c;它简化了开发者构建和管理RESTful API文档的过程。通过自动扫描项目中的接口信息&#xff0c;Knife4j能够生成详细、易读的API文档&#xff0c;无需手动编写和维护。它提供交互式的接口调…

Java由浅入深理解线程池设计和原理

目录 1 线程1.1 什么是线程&#xff1f;什么是进程&#xff1f;1.2 java中线程的实现方式有几种?1.3 线程的生命周期是什么&#xff1f; 2 线程存在的问题2.1 一个线程只能执行一个任务2.2 线程执行完后销毁,无法复用2.3 线程过多,导致JVM宕机 3 初识线程池3.1 了解J.U.C3.2 线…

【算法练习Day1】二分查找移除元素

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 二分查找解决方法一&…

【C语言】指针经典笔试题(上)

C语言的一大重头戏就是指针。 对于指针有一些认识&#xff1a; 1.指针是存放变量的地址&#xff0c;一般说的指针和指针变量是一个概念。 2.地址的单位是字节&#xff0c;大小在不同编译器环境下有所不同&#xff0c;32位机器是4个字节&#xff0c;64位机器是8个字节。 3.数组名…