【C语言系列】C语言内存函数

devtools/2025/3/17 5:34:47/

C语言内存函数

  • 一、memcpy使用和模拟实现
    • 1.1memcpy函数
    • 1.2memcpy函数的模拟实现
  • 二、memmove使用和模拟实现
    • 2.1memmove函数
    • 2.2memmove函数的模拟实现
  • 三、memset函数的使用
    • 3.2memset函数及使用
  • 四、memcmp函数的使用
    • 4.1memcmp函数及使用
  • 五、总结
      • `memcpy` 函数
      • `memmove` 函数
      • `memset` 函数
      • `memcmp` 函数
      • 总结

一、memcpy使用和模拟实现

要理解memcpy的使用和模拟实现首先要看看其函数原型,函数原型如下:

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

1.1memcpy函数

memcpy —— 针对内存块拷贝,包含头文件<string.h>
1.这个函数遇到’\0’的时候并不会停下来。
2.函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
3.如果source和destination有任何的重叠,复制的结果都是未定义的。
下面我们看看它的使用举例:

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

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

1.2memcpy函数的模拟实现

下面我们来进行memcpy函数的模拟实现:
代码如下:

void* my_memcpy(void*dest,const void*src,size_t num)
{
void*ret = dest;
int i = 0;//memcpy函数拷贝完成后,会返回目标空间的起始地址
assert(dest && src);
while(num--)
{
*(char*)dest = *(char*)src;
src = (char*)src + 1;
dest = (char*)dest + 1;
}
return ret;
}

二、memmove使用和模拟实现

要理解memmove的使用和模拟实现首先要看看其函数原型,函数原型如下:

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

2.1memmove函数

注:包含头文件<string.h>
1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
2.如果源空间和目标空间出现重叠,就使用memmove函数处理。
下面我们看看它的使用举例:

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

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

2.2memmove函数的模拟实现

下面我们来进行memmove函数的模拟实现:
memmove函数拷贝完成后,会返回目标空间的起始地址。
代码如下:

void*my_memmove(void*dest,const void*src,size_t num)
{//前 ——> 后
if(dest < src)
{
while(num--)
{
assert(dest && src);
void*ret = dest;
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{//后 ——> 前
while(num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}

三、memset函数的使用

要理解memset的使用和模拟实现首先要看看其函数原型,函数原型如下:

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

3.2memset函数及使用

注:包含头文件<string.h>
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
memset函数的使用代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello world";
memset(arr + 2,'y',7);
printf("%s\n",arr);
return 0;
}

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

#include <stdio.h>
#include <string.h>
int main()
{
int arr[5] = {0};
memset(arr,1,20);//以字节为单位设置的
int i = 0;
for(i = 0;i < 5;i++)
{
printf("%d",arr[i]);
}
return 0;
}

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

四、memcmp函数的使用

要理解memcmp的使用和模拟实现首先要看看其函数原型,函数原型如下:

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

4.1memcmp函数及使用

注:包含头文件<string.h>
memcmp —— 完成内存块的比较
比较从ptr1和ptr2指针指向的位置开始,向后的num个字节内容。
返回值如下图:
在这里插入图片描述
memcmp函数的使用代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = {1,2,3,4,5,6,7};
int arr2[] = {1,2,3,4,8,8,8};
int ret = memcmp(arr1,arr2,20);
printf("%d\n",ret);//-1
return 0;
}

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

五、总结

本文详细探讨了C语言中几个核心内存操作函数的使用方法和原理,包括 memcpymemmovememsetmemcmp。这些函数是处理内存数据的基本工具,广泛应用于高效的内存管理、数据复制、初始化和比较等场景。

memcpy 函数

memcpy 函数的原型为 void *memcpy(void *destination, const void *source, size_t num),其主要功能是将指定数量的字节从源内存块复制到目标内存块。memcpy 的使用前提是源内存和目标内存区域不重叠,因为该函数并不处理内存重叠的情况。在实际应用中,memcpy 主要用于对非重叠内存区域的快速复制。

在模拟实现中,memcpy 通过逐字节复制数据,通过指针递增和内存访问完成复制操作。模拟代码展示了如何通过简单的循环结构,逐步将源地址的数据传输到目标地址。

memmove 函数

memcpy 相似,memmove 也用于内存块的复制,但其不同之处在于,memmove 可以处理内存重叠的情况。其函数原型为 void *memmove(void *destination, const void *source, size_t num)。在源和目标内存区域重叠的情况下,memmove 会根据内存区域的相对位置决定从前向后还是从后向前复制数据,从而保证数据正确传输。

memmove 的实现逻辑包括对内存重叠情况的判断:若目标地址小于源地址,则从前向后复制;若目标地址大于源地址,则从后向前复制,确保数据的正确迁移。

memset 函数

memset 函数的原型为 void *memset(void *ptr, int value, size_t num),其功能是将内存中的指定字节区域初始化为指定的值。该函数广泛应用于内存初始化、清零或者填充操作。例如,在清空数组或设置内存为特定的字节值时,memset 是非常有效的工具。

示例代码展示了如何通过 memset 将字符串和整数数组的部分内容设置为指定值。需要注意的是,memset 按字节处理内存,因此对于多字节类型的数据,可能会产生不可预期的效果。

memcmp 函数

memcmp 函数的原型为 int memcmp(const void *ptr1, const void *ptr2, size_t num),用于比较两块内存区域的内容。函数通过逐字节对比两块内存,从而判断其内容是否相同。返回值为零表示两块内存完全相同,非零值则表示两块内存存在差异。memcmp 常用于内存内容的差异比较或判断两个内存块是否相等。

总结

memcpymemmovememsetmemcmp 是C语言中处理内存数据的基础函数,掌握它们的使用方法对于进行高效的内存操作至关重要。memcpymemmove 都用于内存复制,但 memmove 能够安全地处理内存重叠情况。memset 用于设置内存内容,而 memcmp 用于比较内存区域。理解这些函数的应用场景及其内部实现,有助于程序员在进行内存操作时避免潜在的错误,提升程序的性能和稳定性。

本文通过模拟实现这些函数,进一步深入剖析了其实现原理,帮助读者在实际编程中更灵活地运用这些内存操作函数,理解其背后的机制,并优化内存管理和数据处理策略。


http://www.ppmy.cn/devtools/167741.html

相关文章

数据结构与算法-图论-欧拉路径和欧拉回路(有向图和无向图,骑马修栅栏,单词游戏 play on words)详细代码注解

基础前置知识&#xff1a; 有向图&#xff1a; 欧拉路径&#xff1a; 定义&#xff1a;在有向图中&#xff0c;从一个顶点出发&#xff0c;经过每条边恰好一次&#xff0c;并且遍历所有顶点的路径称为有向图的欧拉路径。 特征&#xff1a;有向图存在欧拉路径&#xff0c;当…

【开原宝藏】30天学会CSS - DAY1 第一课

下面提供一个由浅入深、按步骤拆解的示例教程&#xff0c;让你能从零开始&#xff0c;逐步理解并实现带有旋转及悬停动画的社交图标效果。为了更简单明了&#xff0c;以下示例仅创建四个图标&#xff08;Facebook、Twitter、Google、LinkedIn&#xff09;&#xff0c;并在每一步…

不用 Tomcat?SpringBoot 项目用啥代替?

在SpringBoot框架中&#xff0c;我们使用最多的是Tomcat&#xff0c;这是SpringBoot默认的容器技术&#xff0c;而且是内嵌式的Tomcat。 同时&#xff0c;SpringBoot也支持Undertow容器&#xff0c;我们可以很方便的用Undertow替换Tomcat&#xff0c;而Undertow的性能和内存使…

【小沐学Web3D】three.js 加载三维模型(React)

文章目录 1、简介1.1 three.js1.2 react.js 2、three.js React结语 1、简介 1.1 three.js Three.js 是一款 webGL&#xff08;3D绘图标准&#xff09;引擎&#xff0c;可以运行于所有支持 webGL 的浏览器。Three.js 封装了 webGL 底层的 API &#xff0c;为我们提供了高级的…

在 Linux 64 位系统上安装 Oracle 11g R2 数据库的完整指南

linux.x64_11gR2_database 是 Oracle 数据库 11g 第 2 版&#xff08;11g Release 2&#xff09;的安装包&#xff0c;适用于 64 位 Linux 操作系统。这个安装包包含了在 64 位 Linux 系统上安装 Oracle 数据库所需的全部文件和组件。 安装步骤概述 以下是在 Linux 系统上安装…

(七)Spring Boot学习——Redis使用

有部分内容是常用的&#xff0c;为了避免每次都查询数据库&#xff0c;将部分数据存入Redis。 一、 下载并安装 Redis Windows 版的 Redis 官方已不再维护&#xff0c;你可以使用 微软提供的 Redis for Windows 版本 或者 使用 WSL&#xff08;Windows Subsystem for Linux&a…

C++——STL 常用的排序算法

算法简介&#xff1a; sort // 对容器内元素进行排序reandom_shuffle // 洗牌 指定范围内的元素随机调整次序merge // 容器元素合并&#xff0c;并存储到另一个容器中reverse // 反转指定范围的元素 1. sort 功能描述&#xff1a; 对容器内元素进行排序 函…

卸载Linux自带的MariaDB操作过程

安装及配置 1、下载安装包mysql-version-linux-glibc2.5-x86_64.tar&#xff08;可前往官网自行下载&#xff1a;http://dev.mysql.com/downloads/mysql/&#xff09; 2、卸载系统自带的MariaDB 打开Terminal终端&#xff1a; # rpm -qa|grep mariadb //查询出来已安装的ma…