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

字符串函数的使用与模拟(2)——C语言内存函数

目录

1. memcpy函数的使用与模拟

2. memmove函数的使用与模拟

3. memset函数的使用

4. memcmp函数的使用

5. memchr函数的使用 

前言:C语言内存函数是一组用于直接操作计算机内存的内置函数。使用时要包含头文件<string.h>

1. memcpy函数的使用与模拟

函数原型:

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

(适用于所有数据类型)

使用规则:

  • 复制source所指向的内存数据到内存块destination中。(destination和source是两个内存块的首地址)
  • 复制的数据量是num个字节
  • 该函数不会检查source中是否有终止字符\0,它始终精确复制 num 个字节。
  • 所以num尽量不要超过source的内存大小,避免越界访问。
  • source和destination的内存块不能有重叠,复制的结果都是未定义的。

memcpy函数的模拟实现:

void* my_memcpy(void* dest, const void* src, size_t num)	//内存数据复制函数
{for (int i = 0; i < num; i++){*((char*)dest + i) = *((char*)src + i);}return dest;
}

解析:

  1. 因为dest与src都是void*型的指针,在进行“指针+-整数”操作时要先进行强制类型转换。
  2. 因为num代表的是字节数,所以要强制转换成char*(char的大小是1个字节)

模拟函数的代码验证:

void test(void)
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10];my_memcpy(arr2, arr1, 7 * sizeof(int));
}

my_memcpy前arr2内部的数据如下:

my_memcpy运行后:

2. memmove函数的使用与模拟

函数原型:

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

(适用于所有数据类型)

使用规则:

  • 把source内存块的数据向destination移动复制
  • 向左(或向右)移动,移动的距离是(dest - src)的绝对值
  • 复制的规则与memcpy一样,但在memmove函数中,源内存块和目标内存块是可以重叠的
  • 如果两个内存块是重叠的,dest内存块的数据被source的数据覆盖。

memmove函数的模拟实现:

void* my_memmove(void* dest, const void* src, size_t num)	//8.内存块移动复制(移动的格数是dest-src的绝对值)
{if (dest > src && dest < (char*)src + num)	//情况1:dest位于内存块(src,src+num)中,即dest的值属于该区间{//从右往左复制		for (int i = num - 1; i >= 0; i--) {*((char*)dest + i) = *((char*)src + i);}}else      //情况2:dest位于内存块外,即dest < src或dest > src+num(等于的话两种方向都可以,这里我放在了从左往右){//从左往右复制for (int i = 0; i < num; i++)	{*((char*)dest + i) = *((char*)src + i);}}return dest;
}

解析:

  1. 当dest位于区间src与src+num之间时(情况1):如果是从左往右复制,因为是dest和src都是对同一个数组进行操作,左边被覆盖过的数据 会再次被用来 覆盖右边的数据。所以要从右往左复制
  2. 当dest位于src左边,且内存块重叠时(情况2):同理,为了避免重复覆盖,要从左往右复制
  3. 当dest位于src左边,但内存块无重叠时(情况3):怎样复制都可以。
  4. 当dest位于src右边(情况4:也没有重叠):怎样复制都可以。
  5. 当dest等于src时:怎样复制都可以。

模拟函数的代码验证:

void test(void)
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr1+3, arr1 , 5 * sizeof(int));
}

my_memove运行前:

运行后: 

3. memset函数的使用

函数原型:

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

(适用于所有数据类型)

使用规则:

  • memset是内存块初始化函数。
  • memset可以把ptr指向的内存块中的num个字节都初始化为value
  • 因为是对每个字节进行初始化,所以value的有效范围是-128~127
  • memset常用来把数据初始化为0

我们把两个整型数组分别用memset初始化为“0”和“1”会怎么样?

void test(void)
{int arr1[5];int arr2[5];memset(arr1, 0, 5*sizeof(int));memset(arr2, 1, 5 * sizeof(int));
}

为什么value设成1,初始化结果是16843009 ?

因为memset是把每个字节都设置成value。

(1)当value为0时,这里40个字节的二进制数据是:

00000000 00000000 00000000 00000000 00000000 ……

int型的数据读取4个字节,即00000000 00000000 00000000 00000000,也就是十进制的0

(2)当value为1时,这里40个字节的二进制数据是:

00000001 00000001 00000001 00000001 00000001 ……

int型的数据读取4个字节,即00000001 00000001 00000001 00000001,也就是十进制的16843009

所以memset常用来把数据初始化为0.


4. memcmp函数的使用

函数原型:

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

(适用于所有数据类型)

使用规则:

  • 该函数与strncmp函数的使用方法一样,但适用于所有数据类型。
  • memcmp比较内存块中前num个字节的大小。
  • strncmp和strcmp不同的是,该函数在找到字符\0后不会停止比较

5. memchr函数的使用

函数原型:

const void* memchr(const void* ptr, int value, size_t num);

(常用于字符串)

使用规则:

  • 主要用于在给定的内存区域ptr内查找指定的字符
  • 在内存块的前num个字节寻找字符value。(可以当作strnchr函数,虽然没有这个函数)

本期分享完毕,感谢大家的支持Thanks♪(・ω・)ノ

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Leetcode 165. 比较版本号(Medium)
  • 【C++】——多态详解
  • 新电脑工作流搭建记录-前端篇
  • Nginx从入门到入土(三): 静态资源管理与代理服务
  • 腾讯云2024年数字生态大会开发者嘉年华(数据库动手实验)TDSQL-C初体验
  • npm 安装 与 切换 淘宝镜像
  • 使用 SpringBoot 基础web开发的支持
  • RT-DETR改进策略:BackBone改进|Next-ViT主干赋能下的革命性改进
  • 解决最短路径问题
  • HarmonyOS axios 拦截器处理token 及异常
  • vue websocket 使用
  • 【Ubuntu】虚拟机安装USB摄像头ROS驱动 usb_cam(最新方法)
  • 机器学习--神经网络
  • 一文了解高速工业相机
  • 【Linux】—— muduo网络库的安装配置与使用
  • “大数据应用场景”之隔壁老王(连载四)
  • 10个确保微服务与容器安全的最佳实践
  • AHK 中 = 和 == 等比较运算符的用法
  • C学习-枚举(九)
  • gitlab-ci配置详解(一)
  • Java深入 - 深入理解Java集合
  • JS专题之继承
  • Leetcode 27 Remove Element
  • nginx 负载服务器优化
  • Python实现BT种子转化为磁力链接【实战】
  • ViewService——一种保证客户端与服务端同步的方法
  • Vue 重置组件到初始状态
  • 从零开始的无人驾驶 1
  • 官方解决所有 npm 全局安装权限问题
  • 用element的upload组件实现多图片上传和压缩
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (2)(2.10) LTM telemetry
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (多级缓存)多级缓存
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (函数)颠倒字符串顺序(C语言)
  • (南京观海微电子)——I3C协议介绍
  • (算法)求1到1亿间的质数或素数
  • (原創) 物件導向與老子思想 (OO)
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .aanva
  • .axf 转化 .bin文件 的方法
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net 发送邮件
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • ??eclipse的安装配置问题!??
  • @Autowired自动装配
  • @Builder用法
  • @ComponentScan比较
  • @NotNull、@NotEmpty 和 @NotBlank 区别
  • @property括号内属性讲解