深入探究 C 语言内存函数:memcpy、memmove、memset 和 memcmp

一,常见的内存函数

在 C 语言的编程世界里,对内存的高效操作至关重要。C 标准库为我们提供了一系列强大的内存操作函数,其中 memcpymemmovememset 和 memcmp 这四个函数是处理内存数据的得力助手。接下来,让我们深入了解它们的功能、使用方法以及适用场景。

1. memcpy:简单直接的内存复制

功能

memcpy 函数的主要功能是从源内存地址复制指定数量的字节到目标内存地址。它不关心内存中的内容是否为字符串,只是单纯地按字节进行复制。这使得它在复制数组、结构体等任意类型的数据时非常有用。

原型

void *memcpy(void *dest, const void *src, size_t n);

这里的参数解释如下:

  • dest:指向目标内存区域的指针,数据将被复制到这个位置。
  • src:指向源内存区域的指针,const 修饰表示该函数不会修改源内存中的内容。
  • n:要复制的字节数,这决定了复制操作的范围。

返回值

函数返回指向目标内存区域 dest 的指针,方便我们进行链式操作或后续的内存使用。

示例代码

#include <stdio.h>
#include <string.h>int main() {int src[] = {1, 2, 3, 4, 5};int dest[5];// 使用 memcpy 复制数组memcpy(dest, src, sizeof(src));// 输出复制后的数组for (int i = 0; i < 5; i++) {printf("%d ", dest[i]);}printf("\n");return 0;
}

 

在这个示例中,我们使用 memcpy 将 src 数组的内容复制到 dest 数组中,通过 sizeof(src) 确保复制的字节数与源数组大小一致。

2. memmove:处理重叠内存的复制

功能

memmove 函数的功能和 memcpy 类似,也是从源内存地址复制指定数量的字节到目标内存地址。但它的优势在于能够处理源内存区域和目标内存区域有重叠的情况,会以一种安全的方式进行复制,避免数据覆盖问题。

原型

void *memmove(void *dest, const void *src, size_t n);

参数的含义和 memcpy 相同。

返回值

同样返回指向目标内存区域 dest 的指针。

示例代码

#include <stdio.h>
#include <string.h>int main() {char str[] = "abcdefg";// 有重叠的内存复制memmove(str + 2, str, 3);printf("%s\n", str);return 0;
}

在这个例子中,我们将 str 字符串的前 3 个字符复制到从第 3 个字符开始的位置,由于存在内存重叠,使用 memmove 可以保证复制操作的正确性。

3. memset:内存区域的初始化利器

功能

memset 函数用于将指定内存区域的前 n 个字节设置为指定的值。这在初始化数组、结构体等内存区域时非常方便,比如将数组元素全部初始化为 0。

原型

void *memset(void *s, int c, size_t n);

参数说明如下:

  • s:指向要设置的内存区域的指针。
  • c:要设置的值,通常是一个字符或一个字节大小的整数,在内部会被转换为 unsigned char 类型。
  • n:要设置的字节数。

返回值

返回指向被设置的内存区域 s 的指针。

示例代码

#include <stdio.h>
#include <string.h>int main() {int arr[5];// 将数组元素全部初始化为 0memset(arr, 0, sizeof(arr));// 输出初始化后的数组for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

在这个示例中,我们使用 memset 将 arr 数组的所有元素初始化为 0,通过 sizeof(arr) 确定要设置的字节数。

4. memcmp:内存内容的比较工具

功能

memcmp 函数用于比较两个内存区域的前 n 个字节。它按字节比较两个内存区域的内容,并返回一个表示大小关系的值,常用于比较数组、结构体等数据是否相等。

原型

int memcmp(const void *s1, const void *s2, size_t n);

 

参数解释如下:

  • s1:指向第一个内存区域的指针。
  • s2:指向第二个内存区域的指针。
  • n:要比较的字节数。

返回值

  • 如果 s1 所指向的内存区域小于 s2 所指向的内存区域,返回一个负整数。
  • 如果两个内存区域相等,返回 0。
  • 如果 s1 所指向的内存区域大于 s2 所指向的内存区域,返回一个正整数。

示例代码

#include <stdio.h>
#include <string.h>int main() {int arr1[] = {1, 2, 3};int arr2[] = {1, 2, 3};// 比较两个数组int result = memcmp(arr1, arr2, sizeof(arr1));if (result == 0) {printf("两个数组相等\n");} else {printf("两个数组不相等\n");}return 0;
}

总结

memcpymemmovememset 和 memcmp 这四个内存函数在 C 语言编程中各有其独特的用途。memcpy 适用于简单的非重叠内存复制,memmove 则是处理重叠内存复制的首选,memset 能高效地初始化内存区域,memcmp 可用于比较内存内容。熟练掌握这些函数,能让我们在处理内存数据时更加得心应手,编写出高效、稳定的 C 语言程序。

 

二,模拟实现memcpymemmovememset 和 memcmp内存函数

1. 模拟 memcpy

代码实现
#include <stdio.h>// 模拟 memcpy 函数
void* my_memcpy(void* dest, const void* src, size_t n) {char* d = (char*)dest;const char* s = (const char*)src;for (size_t i = 0; i < n; i++) {d[i] = s[i];}return dest;
}int main() {int arr1[] = {1, 2, 3};int arr2[3];my_memcpy(arr2, arr1, sizeof(arr1));for (int i = 0; i < 3; i++) {printf("%d ", arr2[i]);}return 0;
}
详细讲解
  • 功能:把源内存区域的数据复制到目标内存区域。
  • 参数处理:将 dest 和 src 强制转换为 char* 类型,因为 char 是 1 字节,方便按字节操作。
  • 复制过程:通过 for 循环,从源地址逐字节复制到目标地址,共复制 n 个字节。
  • 返回值:返回目标内存区域的指针。

2. 模拟 memmove

代码实现
#include <stdio.h>// 模拟 memmove 函数
void* my_memmove(void* dest, const void* src, size_t n) {char* d = (char*)dest;const char* s = (const char*)src;if (d < s) {// 目标地址在源地址前面,从前往后复制for (size_t i = 0; i < n; i++) {d[i] = s[i];}} else {// 目标地址在源地址后面,从后往前复制,避免覆盖for (size_t i = n; i > 0; i--) {d[i - 1] = s[i - 1];}}return dest;
}int main() {char str[] = "abcdefg";my_memmove(str + 2, str, 3);printf("%s\n", str);return 0;
}
详细讲解
  • 功能:和 memcpy 类似,但能处理内存重叠的情况。
  • 内存重叠判断:若 dest 地址小于 src 地址,从前往后复制;反之,从后往前复制。
  • 复制过程:根据判断结果,使用 for 循环进行逐字节复制。
  • 返回值:返回目标内存区域的指针。

3. 模拟 memset

代码实现
#include <stdio.h>// 模拟 memset 函数
void* my_memset(void* s, int c, size_t n) {char* p = (char*)s;for (size_t i = 0; i < n; i++) {p[i] = (char)c;}return s;
}int main() {int arr[5];my_memset(arr, 0, sizeof(arr));for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}return 0;
}
详细讲解
  • 功能:将指定内存区域的前 n 个字节设置为指定的值。
  • 参数处理:将 s 强制转换为 char* 类型,方便按字节操作。
  • 设置过程:通过 for 循环,将每个字节设置为 c(转换为 char 类型)。
  • 返回值:返回被设置的内存区域的指针。

4. 模拟 memcmp

代码实现
#include <stdio.h>// 模拟 memcmp 函数
int my_memcmp(const void* s1, const void* s2, size_t n) {const char* p1 = (const char*)s1;const char* p2 = (const char*)s2;for (size_t i = 0; i < n; i++) {if (p1[i] != p2[i]) {return p1[i] - p2[i];}}return 0;
}int main() {int arr1[] = {1, 2, 3};int arr2[] = {1, 2, 3};int result = my_memcmp(arr1, arr2, sizeof(arr1));printf("%d\n", result);return 0;
}
详细讲解
  • 功能:比较两个内存区域的前 n 个字节。
  • 参数处理:将 s1 和 s2 强制转换为 char* 类型,方便按字节比较。
  • 比较过程:通过 for 循环逐字节比较,若发现不同字节,返回它们的差值。
  • 返回值:若都相同返回 0;若 s1 大于 s2 返回正数;若 s1 小于 s2 返回负数。

                                    以上就是详细讲解了模拟实现内存函数的例子

希望这篇文章能帮助你更好地理解和使用这些重要的 C 语言内存函数!如果你在使用过程中遇到任何问题,欢迎在评论区留言交流。

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

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

相关文章

Java 集合

Java 集合 在 Java 编程中&#xff0c;集合框架&#xff08;java.util 包&#xff09;是处理一组对象的强大工具。与数组不同&#xff0c;集合提供了更灵活的数据存储和操作方式。本文将详细介绍 Java 集合框架的核心接口、常用实现类及其应用场景&#xff0c;帮助你更好地理解…

go基本语法

跟Java比较学习。 hello word 示例代码 test1.go文件&#xff1a; // 包路径 package main// 导入模块&#xff0c;下面两种都行 import ("fmt" ) import "log"// main方法 func main() {log.Print("hello word !!!")fmt.Print("hello …

【Docker】如何在Linux、Windows、MacOS中安装Docker

Linux安装Docker 在终端中执行一键安装脚本命令安装docker sudo curl -fsSL https://gitee.com/tech-shrimp/docker_installer/releases/download/latest/linux.sh | bash -s docker --mirror Aliyun1.1 配置docker镜像源 在终端执行 一行命令&#xff0c;编辑配置文件 sudo …

2.24力扣-回溯电话号码的字母组合

17. 电话号码的字母组合 - 力扣&#xff08;LeetCode&#xff09; class Solution {List<String> ans new LinkedList<>();StringBuilder temp new StringBuilder();public List<String> letterCombinations(String digits) {if(digitsnull || digits.leng…

Cocos Creator Shader入门实战(一):材质和Effect的了解

引擎版本&#xff1a;3.8.5 环境&#xff1a; Windows 简介 在Cocos Creator中&#xff0c;游戏炫彩缤纷的效果是借助着色器(Shader)来实现的。 Cocos主要基于OpenGL ES&#xff0c;而Shader的编写则是在可编程渲染管线中基于修改&#xff1a;顶点着色器(Vertex) 和 片段着色…

akka现有的分布式定时任务框架总结

根据你的需求&#xff0c;以下是一些基于 Akka 实现的分布式定时任务框架&#xff0c;以及相关的 GitHub 项目推荐&#xff1a; 1. Openjob Openjob 是一个基于 Akka 架构的新一代分布式任务调度框架&#xff0c;支持多种定时任务、延时任务、工作流设计&#xff0c;采用无中…

微信小程序地图map全方位解析

微信小程序地图map全方位解析 微信小程序的 <map> 组件是一个功能强大的工具&#xff0c;可以实现地图展示、定位、标注、路径规划等多种功能。以下是全方位解析微信小程序地图组件的知识点&#xff1a; 一、地图组件基础 1. 引入 <map> 组件 在页面的 .wxml 文…

Python的PyTorch+CNN深度学习技术在人脸识别项目中的应用

人脸识别技术是一种基于人脸特征进行身份识别的生物识别技术&#xff0c;其核心原理包括人脸检测、人脸对齐、特征提取、特征匹配、身份识别。 一、应用场景 安防&#xff1a;门禁、监控。 金融&#xff1a;刷脸支付、身份验证。 社交&#xff1a;自动标注、美颜。 医疗&am…

《数据库索引设计与优化》译本错误纠正(1)

今天在学习《数据库索引设计与优化》第十一章第198页的时候遇到一个问题&#xff0c;即参数的文字描述与实际不符。我看的是从网络上找到的译本&#xff0c;许多喜欢白嫖的朋友可能也会像我一样遇到这种问题。 可以看到&#xff0c;上面对参数Z的描述是&#xff1a;Z上一次索引…

API测试工具:Swagger vs Postman 2025最新全面对比

随着微服务架构的普及和云原生应用的激增&#xff0c;高效的 API 开发、测试和文档管理工具变得越来越重要。在众多 API 工具中&#xff0c;Swagger 和 Postman 各自以不同的方式解决着 API 开发生命周期中的关键问题&#xff0c;本文将从多个维度深入对比这两款工具&#xff0…

如何查询SQL Server数据库服务器的IP地址

如何查询SQL Server数据库服务器的IP地址 作为数据库管理员或开发人员&#xff0c;了解如何查询SQL Server数据库服务器的IP地址是一项重要技能。本文将介绍几种简单而有效的方法&#xff0c;帮助你轻松获取这一信息。无论你是新手还是经验丰富的专业人士&#xff0c;这些方法…

centos 7 安装python3 及pycharm远程连接方法

安装openssl 使用pip3安装 virtualenv的时候会提示WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. 这是因为缺少openssl 2.0以上版本 解决办法&#xff1a; 一、先确认版本 openssl version 二、安…

AI人工智能之机器学习sklearn-数据预处理和划分数据集

1、概要 本篇学习AI人工智能之机器学习sklearn数据预处理和划分数据集&#xff0c;从代码层面讲述如何进行数据的预处理和数据集划分。 2、简介 本片讲述数据预处理的标准化处理、归一化处理&#xff0c;以常用的两个类为例 标准化处理类 StandardScaler归一化处理类 MinMax…

智能硬件-01智能停车场

行业背景 随着现代人们生活水平的提高&#xff0c;私家车辆在不断增加&#xff0c;小区将面临着临时车用户要多于固定车用户的窘境&#xff0c;尤其是在早晚高峰时段车辆出入拥堵&#xff0c;对小区的车辆管理难度越来越大&#xff0c;对停车场收费员的岗位要求越来越高&#…

定长内存池的实现、测试及错误分析

背景 C/C 申请内存使用的是 malloc &#xff0c;malloc 其实就是一个大众货&#xff0c;什么场景下都可以用&#xff0c;但是什么场景下都可以用就意味着什么场景下都不会有很高的性能。 定长内存池解决固定大小的内存申请释放需求&#xff0c; 性能达到极致&#xff0c;不考…

vue3 下载文件 responseType-blob 或者 a标签

在 Vue 3 中&#xff0c;你可以使用 axios 或 fetch 来下载文件&#xff0c;并将 responseType 设置为 blob 以处理二进制数据。以下是一个使用 axios 的示例&#xff1a; 使用 axios 下载文件 首先&#xff0c;确保你已经安装了 axios&#xff1a; npm install axios然后在你…

Search API:让数据获取变得简单高效的搜索引擎代理商

Search API&#xff1a;让数据获取变得简单高效的搜索引擎代理商 在当今数字化时代&#xff0c;数据驱动的决策变得越来越重要&#xff0c;而获取精准、实时的数据是众多企业、研究机构和开发者的核心需求。然而&#xff0c;直接爬取搜索引擎或行业资讯网站可能会遇到诸多挑战&…

halcon三维对象处理例程总结(二)

目录 一、intersect_plane_object_model_3d二、interactive_intersection三、measure_plant四、moments_object_model_3d五、projective_trans_object_model_3d六、read_object_model_3d_generic_ascii一、intersect_plane_object_model_3d 计算三维物体模型与平面之间的相交部…

基于 Python 的项目管理系统开发

基于 Python 的项目管理系统开发 一、引言 在当今快节奏的工作环境中&#xff0c;有效的项目管理对于项目的成功至关重要。借助信息技术手段开发项目管理系统&#xff0c;能够显著提升项目管理的效率和质量。Python 作为一种功能强大、易于学习且具有丰富库支持的编程语言&…

2月24(信息差)

&#x1f30d;“任意舞蹈任意学”&#xff01;宇树机器人又进化了 传Meta有意合作抛出橄榄枝 &#x1f384;两部门&#xff1a;深入推进公路沿线充电基础设施建设 推动大功率充电技术标准应用 ✨小米15 Ultra、小米SU7 Ultra定档2月27日 雷军宣布&#xff1a;向超高端进发 1.…