C语言中的内存函数使用与模拟实现

ops/2025/3/4 7:40:19/

目录

一、内存函数的使用

1、memcpy()函数

2、memmove()函数

3、memcpy()函数

4、memset()函数:

二、内存函数的模拟实现

1、模拟实现memcpy()函数

2、模拟实现memmove()函数


一、内存函数的使用

1、memcpy()函数

        memcpy()函数可以指定字节数,把源空间的内容拷贝到目的空间中,第一个参数是目的空间,第二个参数是源空间,第三个参数是指定的字节数,该函数的参数和返回值均为void*,可以接收任意类型数据的地址,该函数返回值是目标空间的起始地址。

//memcpy()函数
int main()
{int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int arr1[10] = { 0 };//想要把arr中的20个字节的数据拷贝到arr1中memcpy(arr1, arr, 20);for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);printf("\n");float arr2[10] = { 3.14f, 2.13f, 9.16f, 7.98f, 6.07f, 0.29f };float arr3[10] = { 7.98f, 6.07f, 0.29f };memcpy(arr2, arr3, 20);for (int i = 0; i < 10; i++)printf("%lf ", arr2[i]);return 0;
}

注意:该函数拷贝同样要满足目标空间足够大,拷贝的字节数也不能乱指定。

2、memmove()函数

//memmove()函数
int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };memmove(arr + 2, arr, 20);for (int i = 0; i < 10; i++)printf("%d ", arr[i]);//打印结果为:1 2 1 2 3 4 5 8 9 10return 0;
}

        memmove()函数的功能与memcpy()函数大致相同,只不过一个是可以原地拷贝,另一个是异地拷贝。

3、memcpy()函数

memcmp()函数是比较内存中指定字节内的数据。

//memcmp()函数
int main()
{int arr1[10] = { 1, 2, 3, 4, 5 };int arr2[10] = { 2, 4, 6, 8, 10 };int arr3[10] = { 1, 2, 3, 4, 1 };int arr4[10] = { 1, 2, 3, 4, 5 };printf("%d\n", memcmp(arr1, arr2, 12));//打印结果为:-1printf("%d\n", memcmp(arr1, arr3, 20));//打印结果为:1printf("%d\n", memcmp(arr1, arr4, 20));//打印结果为:0//该函数的返回值与strcmp相同,如果前者小于后者,返回负数,否则返回正数,相等返回0return 0;
}

4、memset()函数:

//memset()函数
int main()
{char str[] = "hello world!";memset(str, 'x', 5);//将字符串str的前5个字节设置为'x'printf("%s\n", str);//打印结果为:xxxxx world!return 0;
}

        memset()函数可以指定字节数来设置内存,设置的值可以自己指定使用该函数时,不能设置常量字符串,另外指定的是字节数,不是元素个数。

//memset()函数
int main()
{int arr[10] = { 0 };memset(arr, 1, sizeof(arr));for (int i = 0; i < 10; i++)printf("%x\n", arr[i]);return 0;
}

上面代码中,将arr数组中的元素的每一个字节都设置成了1。

二、内存函数的模拟实现

1、模拟实现memcpy()函数

//模拟实现memcpy()函数
void* my_memcpy(void* dest, const void* src, size_t size)
{assert(dest && src);void* ret = dest;while (size--){//void*指针不能直接解引用和加减运算*(char*)dest = *(char*)src;dest = (char*)dest + 1;//这样写比((char*)dest)++更加稳定src = (char*)src + 1;}return ret;
}int main()
{int arr[10] = { 1, 2, 3, 4, 5 };int arr1[10] = { 10, 20, 30 };my_memcpy(arr, arr1, 12);for (int i = 0; i < 10; i++)printf("%d ", arr[i]);//打印结果为:10 20 30 4 5 0 0 0 0 0return 0;
}

下面演示自己设计的memcpy()函数在同一块空间的拷贝情况。

//模拟实现memcpy()函数在同一块空间拷贝
void* my_memcpy(void* dest, const void* src, size_t size)
{assert(dest && src);void* ret = dest;while (size--){//void*指针不能直接解引用和加减运算*(char*)dest = *(char*)src;dest = (char*)dest + 1;//这样写比((char*)dest)++更加稳定src = (char*)src + 1;}return ret;
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };my_memcpy(arr + 2, arr, 20);//期望结果1 2 1 2 3 4 5 8 9 10for (int i = 0; i < 10; i++)printf("%d ", arr[i]);//打印结果为:1 2 1 2 1 2 1 8 9 10//出现这种原因的情况是因为内存重叠时候,使用memcpy()函数可能会出问题//那么如果在同一空间下拷贝,通常使用memmove()函数return 0;
}

        C语言的memcpy()函数主要拷贝不重叠的内存,重叠的内存由memmove()函数拷贝,虽然在VS编译器上使用memcpy()函数可能也能拷贝内存重叠的情况,这是因为VS编译器对memcpy()函数功能实现与memmove()函数相同,但不是所有的编译器都这样。

2、模拟实现memmove()函数

//模拟实现memmove()函数
void* my_memmove(void* dest, const void* src, size_t size)
{//使用memcpy()函数出现了内存覆盖,是因为将内存前面的数据拷贝到后面时,运用了从前向后拷贝//所以在实现memmove()函数时,如果将内存前面数据拷贝到后面,应该从后向前拷贝//如果是将内存后面数据拷贝到前面,应该从前向后拷贝,这就分成两种情况讨论//也就是dest<src时候,从前向后拷贝,dest>src时候,从后向前拷贝assert(dest && src);void* ret = dest;if (dest < src)//从前向后拷贝{while (size--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else//从后向前拷贝{while (size --)*((char*)dest + size) = *((char*)src + size);}return ret;
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };my_memmove(arr + 2, arr, 20);for (int i = 0; i < 10; i++)printf("%d ", arr[i]);//打印结果为:1 2 1 2 3 4 5 8 9 10return 0;
}


http://www.ppmy.cn/ops/162503.html

相关文章

《浔川AI翻译v6.1.1版本推迟上线公告》

《浔川AI翻译v6.1.1版本推迟上线公告》 尊敬的浔川用户&#xff1a; 经技术团队审慎评估&#xff0c;原定于2025年3月2日上线的AI翻译v6.1.1版本将推迟至3月9日发布。现将具体情况说明如下&#xff1a; 一、推迟原因与技术说明 在最终复核阶段&#xff0c;系统检测到前端显示…

【Excel】 Power Query抓取多页数据导入到Excel

抓取多页数据想必大多数人都会&#xff0c;只要会点编程技项的人都不会是难事儿。那么&#xff0c;如果只是单纯的利用Excel软件&#xff0c;我还真的没弄过。昨天&#xff0c;我就因为这个在网上找了好久发好久。 1、在数据-》新建查询-》从其他源-》自网站 &#xff0c;如图 …

20250226-代码笔记05-class CVRP_Decoder

文章目录 前言一、class CVRP_Decoder(nn.Module):__init__(self, **model_params)函数功能函数代码 二、class CVRP_Decoder(nn.Module):set_kv(self, encoded_nodes)函数功能函数代码 三、class CVRP_Decoder(nn.Module):set_q1(self, encoded_q1)函数功能函数代码 四、class…

MySQL 存储过程详解

文章目录 1. 存储过程定义1.1 基本概念1.2 核心特点1.3 存储过程 vs 函数 2. 工作原理与示意图2.1 执行流程2.2 示意图 3. 使用场景3.1 复杂业务逻辑3.2 批量数据处理3.3 权限控制3.4 性能优化 4. 示例与说明4.1 基础示例&#xff1a;创建存储过程4.2 带输出参数的存储过程4.3 …

智能合约安全指南 [特殊字符]️

智能合约安全指南 &#x1f6e1;️ 1. 安全基础 1.1 常见漏洞类型 重入攻击整数溢出权限控制缺陷随机数漏洞前后运行攻击签名重放 1.2 安全开发原则 最小权限原则检查-生效-交互模式状态机安全失败保护机制 2. 重入攻击防护 2.1 基本防护模式 contract ReentrancyGuarde…

使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)

引言 在医疗领域&#xff0c;数据就是生命的密码&#xff0c;每一个数据点都可能蕴含着拯救生命的关键信息。特别是在 ICU 这样的重症监护场景中&#xff0c;医生需要实时、准确地了解患者的病情变化&#xff0c;以便做出及时有效的治疗决策。而随着医疗技术的飞速发展&#x…

vue3:四嵌套路由的实现

一、前言 1、嵌套路由的含义 嵌套路由的核心思想是&#xff1a;在某个路由的组件内部&#xff0c;可以定义子路由&#xff0c;这些子路由会渲染在父路由组件的特定位置&#xff08;通常是 <router-view> 标签所在的位置&#xff09;。通过嵌套路由&#xff0c;你可以实…

MySQL DBA技能指南

1. MySQL 安装与配置 安装和部署&#xff1a;掌握 MySQL 在不同操作系统上的安装方法&#xff08;Linux、Windows、Docker 等&#xff09;。配置管理&#xff1a;熟悉 MySQL 配置文件&#xff08;my.cnf 或 my.ini&#xff09;的设置与优化&#xff0c;了解常见的配置参数&…