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

【C语言入门级教学】内存函数

文章目录

  • 1.memcpy使⽤和模拟实现
  • 2.memmove使⽤和模拟实现
  • 3.memset函数的使⽤和模拟实现
  • 4.memcmp函数的使⽤和模拟实现

1.memcpy使⽤和模拟实现

void * memcpy ( void * destination, const void * source, size_t num );//可以拷贝许多类型的数据,所以数据地址类型是void*

功能

• 从源头指向的内存块拷贝固定字节数的数据到目标指向的内存块

• memcpy:memory copy(内存拷贝)

• 要包含头文件==<string.h>==

• 与strcpy函数不同的点:这个函数在遇到 ‘\0’ 的时候并不会停下来,总是精确地拷贝参数传入的字节数

• 如果source和destination有任何的重叠,复制的结果都是未定义的。

参数

destination:指针,指向目标空间,拷贝的数据存放在这里

source:指针,指向源空间,要拷贝的数据从这里来

num:要拷贝的数据占据的字节数

返回值

函数运行结束后返回拷贝后的目的地内存块的起始地址

#include<stdio.h>  
#include<string.h>  
int main() 
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[10] = { 0 }; memcpy(arr2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0;}
//或者
int main()
{float arr1[]={1.2f,2.2f,3.2f,4.2f,5.5f};float arr2[10]={0};
//  memcpy(arr2,arr1,20);memcpy(arr2,arr1,5*sizeof(float));//忘记浮点数的字节数可以这样做return 0;
}

在这里插入图片描述

有个题外话:float型无法精确保存数据

memcpy函数的模拟实现:

void * memcpy ( void * dest, const void * src, size_t num) 
{ void * ret = dest; assert(dest); assert(src); while (num--) { *(char *)dest = *(char *)src;//转换成char*可以一个字节一个字节赋值,但是是临时转换//如果转换为整型,只能四个字节四个字节赋值src=(char*)src+1;//需要再重新转换成char*dest=(char*)dest+1;//不能写成//*(char*)dest++=*(char*)src++;//因为dest和src会先转换成char*,但是++操作会给dest和src++,而不是给(char*)dest和(char*)src进行++操作} return ret; 
}

[注意]

void*不能进行++操作,因为void *是一个指向未知类型的指针类型,它的大小是不确定的。而++操作需要知道指针所指向的对象的大小,才能正确的进行指针运算。

如果出现下段这种代码:

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

分析:因为目标空间和源头空间重复,给arr[4]拷贝时arr[2]已经被拷贝为1了,所以arr[4]会被拷贝现在arr[2]的值,那怎么解决这个问题呢,可以用memmove函数(但是vs编译器的memcpy可以拷贝重叠空间,属于超额完成任务)

2.memmove使⽤和模拟实现

void * memmove ( void * destination, const void * source, size_t num );//和memcpy参数一样

功能

• memmove函数也是完成内存拷贝的

• memmove函数处理的源内存块和⽬标内存块是可以重叠,也可以不重叠。

• 需要包含头文件==<string.h>==

参数

destination:指针,指向目标空间,拷贝的数据存放在这里

source:指针,指向源空间,要拷贝的数据从这里来

num:要拷贝的数据占据的字节数

返回值

函数运行结束后,返回目标空间的起始地址

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

输出的结果: 1 2 1 2 3 4 5 8 9 10

memmove的模拟实现:

在这里插入图片描述

第二种方法

#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;dest=(char*)dest+1;src=(char*)src+1;}}else{while(num--){*((char*)dest+num)=*((char*)src+num);}}return ret;//与memmove函数保持一致
}
int main() 
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); }return 0; 
}

第一种方法

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

3.memset函数的使⽤和模拟实现

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

功能

• memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

• 需包含头文件==<string.h>==

参数

ptr:指针,指向要设置的内存空间,存放了要设置的内存空间的起始地址

value:要设置的值,函数将会把value值转换成unsigned char的数据进行设置的,也就是以字节为单位来设置内存块的

num:要设置的内存长度,单位是字节

返回值

函数运行完之后返回要设置的内存空间的起始位置

#include<stdio.h>  
#include<string.h>
int main () 
{ char str[] = "hello world"; memset (str,'x',6); printf(str); return 0; 
}

输出的结果: xxxxxxworld

[注意]

memset函数对内存单元的设置是以字节为单位的

int main()
{int arr[10]={0};memset(arr,1,40);return 0;
}

结果如下:发现每个字节都设置为1,而不是00 00 00 01
在这里插入图片描述

4.memcmp函数的使⽤和模拟实现

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

功能

• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节

• 需包含头文件==<string.h>==

参数

ptr1:指针,指向一块待比较的内存块

ptr2:指针,指向另外一块待比较的内存块

num:指定的比较长度,单位是字节

返回值
在这里插入图片描述

示例一:

int main()
{int arr1[]={1,2,3,4,5,6,7,8,9,10};int arr2[]={1,2,3,4,8};int r=memcmp(arr1,arr2,17);if(r>0)printf(">\n");else if(r<0)printf("<\n");elseprintf("=\n");return 0;
}

在这里插入图片描述
示例二:

#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); else  printf("'%s' is the same as '%s'.\n", buffer1, buffer2); return 0; 
}

在这里插入图片描述


文章转载自:

http://vBS03ScM.rkgyx.cn
http://YasI8T20.rkgyx.cn
http://PCUvDDhF.rkgyx.cn
http://ZT2vO0nc.rkgyx.cn
http://P2egGjwU.rkgyx.cn
http://imIT8VJY.rkgyx.cn
http://KNNCeYT0.rkgyx.cn
http://g90owPN4.rkgyx.cn
http://y1FpL25J.rkgyx.cn
http://T2FoQKZ4.rkgyx.cn
http://1Fx6S2in.rkgyx.cn
http://eI4EECfn.rkgyx.cn
http://YajXuora.rkgyx.cn
http://1I4IKzRy.rkgyx.cn
http://yFGCNEbz.rkgyx.cn
http://sdAamuEi.rkgyx.cn
http://XCvuyZ8x.rkgyx.cn
http://W7atqn4D.rkgyx.cn
http://RIPZJDsS.rkgyx.cn
http://YHONId5t.rkgyx.cn
http://ZzY5Z6fS.rkgyx.cn
http://CaEKmbux.rkgyx.cn
http://q4JNAjEb.rkgyx.cn
http://rGOEaVN7.rkgyx.cn
http://UQx9Nxld.rkgyx.cn
http://qguONtiU.rkgyx.cn
http://8Lq7o0h3.rkgyx.cn
http://A7MJUskl.rkgyx.cn
http://0CsRDmGz.rkgyx.cn
http://rwZ38nMP.rkgyx.cn
http://www.dtcms.com/a/373817.html

相关文章:

  • 第三届“陇剑杯”CTF比赛部分WP(Web部分和应急)
  • 人工智能-python-深度学习-神经网络VGG(详解)
  • Spring框架重点概述
  • vue2+el的树形穿梭框
  • JuiceFS分布式文件系统
  • 【数据结构】简介
  • MindShow AI:高效生成思维导图的实用AI工具
  • python 通过selenium调用chrome浏览器
  • Spring Cloud Alibaba快速入门02-Nacos(中)
  • Redis集群(redis cluster (去中心化))
  • 无人机航拍数据集|第39期 无人机玉米雄穗目标检测YOLO数据集776张yolov11/yolov8/yolov5可训练
  • PCB下单厂家有哪些?可pcb在线下单厂家
  • 安卓服务的两种启动方式有什么区别
  • Spring Cloud Alibaba 是什么,怎么简单搭建
  • ARM-寄存器与异常处理全解析
  • 2024年6月GESPC++三级真题解析(含视频)
  • 【面试题】Transformer应用实践专题
  • 借助Wisdom SSH,轻松搭建私有云盘
  • Linux基础知识(三)
  • Flink KeyedProcessFunction为什么能为每个key定义State和Timer?
  • 【ARDUINO】通过ESP8266连接WIFI,启动TCP,接受TCP客户端指令【待测试】
  • Azure Data Factory (ADF) vs Azure Logic Apps: 对比分析
  • 软考-系统架构设计师 企业资源规划(ERP)详细讲解
  • 农产品运输与调度服务平台的设计与实现
  • Dart → `.exe`:Flutter 桌面与纯命令行双轨编译完全指南
  • 栈专题之每日温度
  • 远场学习_FDTD_dipole(1)
  • 编译缓存工具 sccache 效果对比
  • 【MFC典型类和函数:CString的字符串魔法与Afx全局函数的便利店】
  • 【MFC】对话框属性:字体 (Font Name) 和 大小 (Font Size)