C语言部分内存函数详解

news2024/9/22 6:13:45

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.coloradmin.cn/o/2054384.html

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

相关文章

C#使用onnxruntime加载模型,部署到别人的PC上报错

C#使用onnxruntime加载模型&#xff0c;部署到别人的PC上报错 C#使用onnxruntime加载模型&#xff0c;部署到别人的PC上报错解决方案 C#使用onnxruntime加载模型&#xff0c;部署到别人的PC上报错 C#使用onnxruntime加载模型&#xff0c;部署到别人的PC上报错&#xff1a; Sys…

Python Web 应用和数据处理任务库之Redis Queue (RQ) 使用详解

概要 在现代 Web 应用和数据处理任务中,后台任务处理是一个非常重要的部分。Redis Queue (RQ) 是一个使用 Redis 作为消息队列的简单 Python 库,专注于处理异步任务。RQ 易于设置和使用,适用于需要后台处理的 Web 应用或数据处理项目。本文将详细介绍 RQ 库,包括其安装方法…

火狐如何离线继承配置

陪伴自己6年的电脑&#xff0c;因为CPU烧了&#xff0c;导致一些配置没导出来&#xff0c;其中包括浏览器的收藏记录、网站密码。 火狐浏览器离线继承配置 把老电脑的C盘取出&#xff0c;插入硬盘盒中&#xff0c;找到C:\Users\用户名\AppData\Roaming\Mozilla\Firefox\Profile…

【MySQL】JDBC的基础使用

系列文章目录 第一章 数据库基础 第二章 数据库基本操作 第三章数据库约束 第四章表的设计 第五章查询进阶 第六章索引和事务 文章目录 系列文章目录前言一、JDBC基本概念二、JDBC的准备工作三、JDBC-Demo小结 四、JDBC进阶写法总结 前言 在前面对MySQL已经有了基本的认知&am…

分类预测|基于白鲸优化混合核极限学习机结合Adaboost的数据分类预测Matlab程序BWO-HKELM-Adaboost

分类预测|基于白鲸优化混合核极限学习机结合Adaboost的数据分类预测Matlab程序BWO-HKELM-Adaboost 文章目录 前言分类预测|基于白鲸优化混合核极限学习机结合Adaboost的数据分类预测Matlab程序BWO-HKELM-Adaboost 一、BWO-HKELM-Adaboost模型1. 模型组成1.1 白鲸优化算法&#…

Arco Design,字节跳动出品的UI库

Arco Design是字节跳动出品的UI库&#xff0c;支持Vue和React。还是比较美观的。并且Arco Design还提供了中后台模版。但是通过提供的arco-cli连接了github&#xff0c;正常情况下无法构建。但效果还是挺好的&#xff0c;下面是效果图&#xff1a; 更新&#xff1a; 传送门可…

用C#写一个随机音乐播放器

form1中namespce里的代码如下 public partial class Form1 : Form {public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){string folder textBox1.Text;string folderPath folder; // 指定音频文件所在的文件夹路径OpenRandomFi…

C#关于多线程的线程问题

using System.Text; ​ namespace 平时练习8._19day06 {internal class Program{static async Task Main(string[] args){Console.WriteLine(Thread.CurrentThread.ManagedThreadId );StringBuilder sb new StringBuilder();for (int i 0; i < 10000; i){sb.Append("…

嵌入式系统:全面解读与关键要点

嵌入式系统&#xff0c;这个看似专业而遥远的技术词汇&#xff0c;其实早已渗透进了我们日常生活的方方面面。从智能手机到家用电器&#xff0c;再到汽车中的电子控制系统&#xff0c;嵌入式系统无处不在。你是否好奇它们是如何工作的&#xff0c;又有哪些关键点值得我们关注&a…

Android12 显示框架之Transaction----client端

目录&#xff1a;Android显示终极宝典 在前面的章节中&#xff0c;应用通过createSurface()在surfaceflinger中创建了一层layer&#xff0c;紧接着要做的事情就是对这个layer设置一些属性&#xff08;或者叫状态&#xff09;&#xff0c;常设置的属性有位置、大小、z-order等等…

RM悬挂系统

悬挂系统是汽车的车架与车桥或车轮之间的一切传力连接装置的总称&#xff0c;其作用是传递作用在车轮和车架之间的力和力扭&#xff0c;并且缓冲由不平路面传给车架或车身的冲击力&#xff0c;并衰减由此引起的震动&#xff0c;以保证汽车能平稳地行驶。 其主要由减震器和弹簧组…

PictureSelector自定义路径首页不显示数据的问题

1、依赖导入和源码查看 网址&#xff1a;https://github.com/LuckSiege/PictureSelector/tree/version_component 使用PictureSelector 2、自定义路径的实现&#xff1a; 使用方法&#xff1a;setLoaderFactoryEngine进行设置 见[read.md] (https://github.com/LuckSiege/Pi…

C++ wxWidgets图形界面开发用什么IDE最好?

在主流免费的IDE工具中&#xff0c;我们可以想到的支持cmake项目的工具就只有QtCreator&#xff0c;VisualStudio&#xff0c;VSCode这三个。其中QtCreator和VSCode支持WIndows&#xff0c;Mac&#xff0c;WIndows三大主流平台。但是VSCode在Ubuntu等系统下的支持并没有在WIndo…

VMware Esxi 7.0 安装P40显卡疑难杂症小诊断

第一章、小叙 今天安装一台X99主板的机器&#xff0c;操作系统是VMware Esxi 7.0&#xff0c;配备一张P40显卡&#xff0c;显卡已在Esxi硬件中识别到&#xff0c;但是无法安装驱动&#xff0c;安装完驱动之后无法分配给虚拟机&#xff0c;如图所示为识别的硬件。 第二章、安装显…

Spark-SparkSubmit详细过程

一、概览 《Spark-环境启动》中讲了Spark环境的启动&#xff0c;以及Master和多个Worker之间时基于Endpoint之间的Netty通信&#xff0c;也被称为Spark的RpcEnv。在此基础上我们来看下spark-submit是如何将我们写的Spark程序调起的 二、启动脚本示例&#xff1a; spark-subm…

css通过keyframes实现文字定时向上滚动

一、效果 二、代码 <!DOCTYPE html> <html lang="en"><head>

软考软件设计师-备考须知

&#x1f939;‍♀️潜意识起点&#xff1a;个人主页 &#x1f399;座右铭&#xff1a;得之坦然&#xff0c;失之淡然。 &#x1f48e;擅长领域&#xff1a;大前端 是的&#xff0c;我需要您的&#xff1a; &#x1f9e1;点赞❤️关注&#x1f499;收藏&#x1f49b; 是我…

【hot100篇-python刷题记录】【矩阵置零】

R5-矩阵篇 印象题&#xff0c;思路即可&#xff1a; 手动置0 无非就是行和列都置0 使用thex和they将该元素的i和y存储起来&#xff0c;再分别遍历thex&#xff0c;将所有y的位置置0 遍历they&#xff0c;将所有x 置0 class Solution:def setZeroes(self, matrix: List[List…

【机器学习】(基础篇六) —— 数据集的划分和过拟合问题

数据集的划分 训练集和测试集 在机器学习中&#xff0c;数据集通常会被划分为训练集&#xff08;Training Set&#xff09;和测试集&#xff08;Test Set&#xff09;&#xff0c;有时还会包括一个验证集&#xff08;Validation Set&#xff09;。这样的划分是为了能够更好地…

Ⅰ、基于 WebGPU 从 0 到 1 渲染 GLTF:第一个三角形

Ⅰ、基于 WebGPU 从 0 到 1 渲染 GLTF&#xff1a;第一个三角形 WebGPU 是一种面相网页的现代图形 API&#xff0c;由主要浏览器供应商开发。与 WebGL 相比&#xff0c;WebGPU 对 GPU 提供了更直接的控制&#xff0c;使应用程序能更有效地利用硬件&#xff0c;类似于 Vulkan 和…