C语言部分内存函数详解

C语言部分内存函数详解

  • 前言
  • 1.`memcpy`
    • 1.1基本用法
    • 1.2注意事项
      • **目标空间与原空间不能重叠**
      • **目标空间原数据会被覆盖**
      • **目标空间要够大**
      • **拷贝字节数需小于原空间大小**
    • 1.3模拟实现
  • 2.`memmove`
    • 2.1基本用法
    • 2.2注意事项
    • 2.3模拟实现
  • 3.`memset`
    • 3.1基本用法
  • 4.`memcmp`
    • 4.1基本用法
    • 4.2注意事项
      • **按字节比较**

前言

在我的C语言-部分字符串函数详解 1-4和C语言-部分字符串函数详解 5-10中,函数的操作对象为字符串,如果想处理其他类型的数据,则需用到内存函数
本文将介绍<string.h>头文件下的部分内存函数:

  • 1.memcpy
  • 2.memmove
  • 3.memset
  • 4.memcmp

1.memcpy


函数原型:void * memcpy ( void * destination, const void * source, size_t num );
简介:Copy block of memory——拷贝一块内存

1.1基本用法

会从source向后拷贝num字节的内容至destination

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 5*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:
在这里插入图片描述

1.2注意事项

目标空间与原空间不能重叠

如果重叠,拷贝的结果未定义,需使用memmove处理重叠的情况。
在VS2022上,重叠对拷贝结果无影响:

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr1+3, arr1, 5*sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);

运行结果:
在这里插入图片描述

但C语言标准中拷贝的结果未定义,因此仍不建议使用memcpy拷贝有重叠的情况。

目标空间原数据会被覆盖

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 9,9,9,9,9 };
memcpy(arr2, arr1, 5*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:
在这里插入图片描述

目标空间要够大

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5];
memcpy(arr2, arr1, 10*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:
在这里插入图片描述

VS2022给出了相应的警告:在这里插入图片描述

拷贝字节数需小于原空间大小

int arr1[5] = { 1,2,3,4,5 };
int arr2[10];
memcpy(arr2, arr1, 10 * sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr2[i]);

运行结果:
在这里插入图片描述

VS2022给出了相应的警告:在这里插入图片描述

1.3模拟实现

void* my_memcpy(void* dst, const void* src, size_t num)
{assert(dst && src);void* ret = dst;while (num--)*((char*)dst)++ = *((char*)src)++;return ret;
}

为了处理多种类型的数据,我们传入void*的指针,在强转成char,这样在拷贝时可以按字节依次拷贝。

2.memmove


函数原型:void * memmove ( void * destination, const void * source, size_t num );
简介:Move block of memory——拷贝一块内存

2.1基本用法

memmovememcpy的用法基本一致,且memmove可处理有重叠的空间。

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 3, arr1, 5 * sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);

运行结果:
在这里插入图片描述

2.2注意事项

memcpy的基本一致,且memmove可处理有重叠的空间。

2.3模拟实现

memcpy的模拟实现中,我只是单方向的进行拷贝,完成了C语言对memcpy的基本要求。
而在memmove的模拟实现中,如果单方向进行拷贝,会在空间重叠时出现拷贝了新数据的现象,因此需判断拷贝方向。

void* my_memmove(void* dst, const void* src, size_t num)
{assert(dst && src);void *ret = dst;if (dst < src){while (num--)*((char*)dst)++ = *((char*)src)++;return ret;}else{while (num--)*(((char*)dst) + num) = *(((char*)src) + num);return ret;}
}

3.memset


函数原型:void * memset ( void * ptr, int value, size_t num );
简介:Fill block of memory——填充内存块

3.1基本用法

按字节设置内存,可用于初始化

typedef struct Peo
{char name[20];int age;char tele[12];
}Peo;
typedef struct Contact
{struct Peo peo[100];int num;
}Contact;
int main()
{Contact con;Contact* p = &con;memset(p->peo, 0, sizeof(p->peo));return 0;
}

这段代码是我写的通讯录里的。
定义了两个结构体类型 PeoContactPeo 结构体包含姓名、年龄和电话号码。而 Contact 结构体则包含一个 Peo 类型的数组,以及一个整型变量 num,用于记录实际存储了多少个联系人。

main 函数中,首先创建了一个 Contact 类型的变量 con,接着定义了一个指向 Contact 类型的指针 p 并将其指向 con。然后使用 memset 函数将 p->peo 数组中的所有元素初始化为0

初始化效果:

对于 char 类型的数组,这会使它们只包含空字符。
对于 int 类型的成员,这会将它们初始化为0
数组大小:sizeof(p->peo) 返回的是整个 peo 数组的大小,即100个 Peo 结构体的总大小。

4.memcmp


函数原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
简介:Compare two blocks of memory——比较两个内存块

4.1基本用法

char ch1[] = "aaaa";
char ch2[] = "aaab";
int n= memcmp(ch1, ch2, 4);
if (n > 0)printf(">");
else if (n < 0)printf("<");
else printf("=");

运行结果:
在这里插入图片描述

4.2注意事项

按字节比较

不管什么类型的数据,memcmp都是按字节比较,这使得有时候不能得到预期结果:

int arr1[10] = { 1 };
int arr2[10] = { 256 };
int n = memcmp(arr1, arr2, 4);
if (n > 0)printf(">");
else if (n < 0)printf("<");
else printf("=");

运行结果:
在这里插入图片描述
1肯定比256小,但我们比的规则是逐字节
在小端存储的机器上:
1在内存:
在这里插入图片描述
256在内存:
在这里插入图片描述
由于是逐字节比较,所以结果是1>256


希望本篇文章对你有所帮助!
本人仅仅是个C语言初学者,如有任何意见,欢迎各位提出!


相关文章:
C语言指针详解-上
C语言指针详解-下

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

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

相关文章

[论文笔记]ZeRO: Memory Optimizations Toward Training Trillion Parameter Models

引言 今天带来ZeRO: Memory Optimizations Toward Training Trillion Parameter Models的论文笔记。 大型深度模型提供了显著的准确性提升&#xff0c;但训练数十亿到数万亿个参数是具有挑战性的。现有的解决方案&#xff0c;如数据并行和模型并行&#xff0c;存在基本的局限…

python小游戏之摇骰子猜大小

最近学习Python的随机数&#xff0c;逻辑判断&#xff0c;循环的用法&#xff0c;就想找一些练习题&#xff0c;比如小游戏猜大小&#xff0c;程序思路如下&#xff1a; 附上源代码如下&#xff1a; 摇骰子的函数&#xff0c;这个函数其实并不需要传任何参数&#xff0c;调用后…

【Delphi】中多显示器操作基本知识点

提要&#xff1a; 目前随着计算机的发展&#xff0c;4K显示器已经逐步在普及&#xff0c;笔记本的显示器分辨率也都已经超过2K&#xff0c;多显示器更是普及速度很快。本文介绍下Delphi中操作多显示器的基本知识点&#xff08;Windows系统&#xff09;&#xff0c;这些知识点在…

【Java】 方法引用与Lambda(快速上手)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 方法引用 五、总结&#xff1a; 一、前言 Calculator::plus看到::好奇有什…

使用多种机器学习模型进行情感分析

使用 TF-IDF 与贝叶斯分类器进行情感分析是一个常见且有效的组合&#xff0c;特别是在文本分类任务中。贝叶斯分类器&#xff08;通常是朴素贝叶斯分类器&#xff09;等机器学习模型具有计算简单、效率高的优点&#xff0c;且在文本分类任务中表现良好。接下来&#xff0c;我将…

eNSP 华为ACL配置

华为ACL配置 需求&#xff1a; 公司保证财务部数据安全&#xff0c;禁止研发部门和互联网访问财务服务器&#xff0c;但总裁办不受影响 R1&#xff1a; <Huawei>sys [Huawei]sys Router1 [Router1]undo info-center enable [Router1]int g1/0/0 [Router1-GigabitEth…

语音助手Verbi:科技创新的未来

今天&#xff0c;我要向大家介绍一个名为Verbi的语音助手项目。这是一个结合了多种先进技术的模块化语音助手应用程序&#xff0c;能够实现语音到文本、文本生成和文本到语音的全流程处理。通过这个项目&#xff0c;我们可以体验到尖端科技如何改变我们的日常生活。 Verbi的诞…

ubuntu配pip的源

临时使用源 pip install [包名] -i [pip源URL]# 示例 pip install pytest -i https://pypi.tuna.tsinghua.edu.cn/simple更换配置pip镜像源 step1&#xff1a;创建一个配置文件 mkdir ~/.pip/ cd .pip sudo vim pip.conf step2:填写源信息&#xff0c;保存并退出【:wq】 [g…

文件包含漏洞(一)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 一&#xff0c;漏洞简述。 文件包含漏洞&#xff0c;通常发生在Web应用程序中&#xff0c;特别是那些使用用户输入动态生成内容的部分。这种漏洞允许攻击者通过提交恶意的文件路径请…

10 个 C# 关键字和功能

在 Stack Overflow 调查中&#xff0c;C# 语言是排名第 5 位的编程语言。它广泛用于创建各种应用程序&#xff0c;范围从桌面到移动设备再到云原生。由于有如此多的语言关键字和功能&#xff0c;对于开发人员来说&#xff0c;要跟上新功能发布的最新信息将是一项艰巨的任务。本…

C语言——操作符详解

目录 1.操作符的分类 2.原码、反码和补码 3.移位操作符 3.1 左移操作符 3.2 右移操作符 4.位操作符 4.1 按位与& 4.2 按位或| 4.3 按位异或^ ​编辑 4.4 按位取反~ 4.5 应用题 4.5.1 题目&#xff1a;不能创建临时变量&#xff0c;实现两个整数的交换 4.5.2 …

本地下载安装WampServer结合内网穿透配置公网地址远程访问详细教程

文章目录 前言1.WampServer下载安装2.WampServer启动3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 Wamp 是一个 Windows系统下的 Apache PHP Mysql 集成安装环境&#xff0c;是一组常用来…

FFMPEG推流器讲解

FFMPEG重要结构体的讲解 FFMPEG中有六个比较重要的结构体&#xff0c;分别是AVFormatContext、AVOutputFormat、 AVStream、AVCodec、AVCodecContext、AVPacket、AVFrame、AVIOContext结构体&#xff0c;这几个结构体是贯穿着整个FFMPEG核心功能。 AVFormatContext 这个结构…

nginx基础配置

1. https配置 首先在nginx.conf中配置https 2. 重定向 rewrite ^/(.*)$ https://www.sxl1.com/$1 permanent;3. 自动索引 autoindex on;4. 缓存 Nginx expire缓存配置: 缓存可以降低网站带宽&#xff0c;加速用户访问location ~ .*\.(gif|jpg|png)$ {expires 365d;roo…

react最好用的swiper插件和拖动插件 react-tiny-slider react-draggable

react移动端项目&#xff0c;其实有挺多的ui框架的&#xff0c;但是我们公司的项目&#xff0c;都是自己封装的ui库&#xff0c;又不可能为了一个轮播图就去再安装一个ui库 所以找了很多的轮播插件&#xff0c;都是不能满足需求 最后找到了它&#xff0c;react-tiny-slider&…

Windows Microsoft Edge 浏览器 配置【密码】

在浏览 Web 时&#xff0c;Microsoft Edge 可以轻松保存密码。 在桌面或移动设备上的 Edge 浏览器中输入新密码时&#xff0c;Microsoft Edge 会询问你是否要记住用户名和密码。 下次访问该网站时&#xff0c;浏览器将完成帐户信息的填写。 如果使用 Microsoft 帐户登录到 Edg…

redis集合若干记录

无序集合 redis通常使用字典结构保存集合数据&#xff0c;字典健存储集合元素&#xff0c;字典值为空。如果一个集合全为整数&#xff0c;使用字典就有点浪费了&#xff0c;redis使用intset保存。 插入元素到intset中 获取插入元素编码&#xff0c;如果插入元素编码级别高于int…

机器学习 之 sklearn的使用介绍和如何找到API

scikit-learn&#xff08;简称 sklearn&#xff09;是基于python语言的一个第三方机器学习库&#xff0c;它提供了简单而有效的工具来进行数据分析和建模。建立在numpy pandas SciPy和Malpotlib库上&#xff0c;下面是对如何使用 sklearn 以及如何找到其 API 的一个基本介绍&am…

仿RabbiteMq实现简易消息队列正式篇(需求分析)

TOC 目录 MQ的实现方法 RabbitMq中的相关概念 消息队列系统模块划分 总体划分 服务端模块 数据管理模块 虚拟机数据管理模块 交换机路由模块 消费者管理模块 信道&#xff08;通信&#xff09;管理模块 连接管理模块 服务端BrokerServer模块 客户端模块 消费者管…

MySQL-MVCC举例说明

在数据库系统中&#xff0c;多版本并发控制&#xff08;MVCC, Multi-Version Concurrency Control&#xff09; 是一种用于提高并发性能的机制&#xff0c;它允许多个事务同时读取和写入数据&#xff0c;而不会产生锁等待和阻塞的问题。MySQL 的 InnoDB 存储引擎广泛使用了 MVC…