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

devtools/2025/2/28 19:41:48/

一,常见的内存函数

在 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.ppmy.cn/devtools/163427.html

相关文章

stm32四种方式精密控制步进电机

在搭建完clion的开发环境后&#xff0c;我决定重写之前的项目并优化完善&#xff0c;争取做出完全可落地的东西&#xff0c;也结合要写的论文内容一同学习下去。 因此&#xff0c;首当其冲的就是回到步进电机控制领域&#xff0c;把之前使用中断溢出进行步进电机控制的方案进行…

深入理解 CSS pointer-events: none:穿透点击的魔法

一、什么是 pointer-events: none&#xff1f; pointer-events: none 是一个强大的 CSS 属性&#xff0c;它控制元素是否响应鼠标/触摸事件&#xff08;如点击、悬停、拖拽&#xff09;。当设置为 none 时&#xff0c;元素会变得“透明”&#xff0c;事件会直接穿透到下方的元…

linux vim 撤销 回退操作

在Linux的vim编辑器中&#xff0c;撤销和回退操作是非常基本的&#xff0c;但它们可以通过不同的方式实现&#xff0c;具体取决于你想要的精确效果。下面是一些常用的方法&#xff1a; 1. 撤销&#xff08;Undo&#xff09; 单个撤销&#xff1a; 你可以通过按下u键来撤销上一…

java项目之基于ssm的线上旅游体验系统(源码+文档)

项目简介 基于ssm的线上旅游体验系统实现了以下功能&#xff1a; 用户信息管理&#xff1a; 用户信息新增 用户信息修改 景点信息管理&#xff1a; 景点信息添加 景点信息删除 景点信息修改 景点类型管理&#xff1a; 景点类型添加 景点类型删除 景点类型修改 景点留言管理…

REACT学习第三幕--沉睡花园

什么是Hooks&#xff1f; 在react中&#xff0c;useState以及任何其他以use开头的函数都称为Hook&#xff08;钩子&#xff09;&#xff0c;所以Hooks就是代表着use函数的集合&#xff0c;也就是钩子的集合 Hooks就是一堆功能函数&#xff0c;一个组件想要实现哪些功能就可以…

DeepSeek开源:FlashMLA深度解析:Hopper架构上的大模型推理革命

2025年2月24日,DeepSeek以「开源周」首日发布的FlashMLA技术,重新定义了Hopper架构GPU在AI推理领域的性能极限。这款专为NVIDIA H800/H100系列优化的MLA(Multi-head Latent Attention)解码内核,通过突破性算法设计与硬件协同优化,在可变长度序列处理场景中实现了3000GB/s…

sklearn中的决策树-分类树:剪枝参数

剪枝参数 在不加限制的情况下&#xff0c;一棵决策树会生长到衡量不纯度的指标最优&#xff0c;或者没有更多的特征可用为止。这样的决策树 往往会过拟合。为了让决策树有更好的泛化性&#xff0c;我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大&#xff0c;正确的剪枝策…

Shor算法:解密现代加密技术的未来武器

Shor算法:解密现代加密技术的未来武器 大家好,我是Echo_Wish。今天我们要探讨一个充满未来感的话题:Shor算法在现代加密破解中的潜力。自从量子计算机的概念提出以来,人们一直在研究它对现代加密技术的影响。而Shor算法正是其中的核心,它具有破解目前广泛使用的RSA加密的…