首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【深入详解】C语言内存函数:memcpy、memmove的使用和模拟实现,memset、memcmp函数的使用

【深入详解】C语言内存函数:memcpy、memmove的使用和模拟实现,memset、memcmp函数的使用

作者头像
艾莉丝努力练剑
发布2025-11-13 09:53:28
发布2025-11-13 09:53:28
2220
举报
文章被收录于专栏:C / C++C / C++

🔥个人主页:艾莉丝努力练剑 🍓专栏传送门:《C语言》 🍉学习方向:C/C++方向 ⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平



前言:前面几篇文章介绍了c语言的一些知识,包括循环、数组、函数、VS实用调试技巧、函数递归、操作符、指针、字符函数和字符串函数、结构体、联合和枚举、动态内存管理、文件操作、编译和链接、预处理等,在这篇文章中,我将开始介绍C语言内存函数的一些重要知识点!对C语言内存函数感兴趣的友友们可以在评论区一起交流学习!


一、memcpy、memmove使用和模拟实现

(一)memcpy的使用和模拟实现

memcmp:memory copy——内存拷贝;

代码原型:

代码语言:javascript
复制
void* memcpy(void* destination, const void* source, size_t num);

三板斧——

功能: (1)memcpy 是完成内存块拷贝的,不关注内存中存放的数据是什么; (2)函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存 位置; (3)如果 source 和 destination 有任何的重叠,复制的结果都是未定义的 (内存重叠的情况使用memmove 就行)。 注: memcpy 的使用需要包含 <string.h>。 参数: destination :指针,指向目标空间,拷贝的数据存放在这里; source :指针,指向源空间,要拷贝的数据从这里来; num :要拷贝的数据占据的字节数。 返回值: 拷贝完成后,返回目标空间的起始地址。

1、代码演示:
(1)memcpy拷贝整型

strcpy、strncpy拷贝字符串的,是有局限性的; 拷贝一个整型数组呢?结构体数组呢?

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS  1

#include<stdio.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//             0 1 2 3 4 5...
	int arr2[20] = { 0 };
	//             0 1 2 3 4 5...
	//想把arr1中的10个整数,拷贝到arr2中
	//循环遍历
	//memcpy
	memcpy(arr2, arr1, 40);

	return 0;
}
(2)memcpy拷贝浮点型
代码语言:javascript
复制
#include<stdio.h>

int main()
{
	int arr1[] = { 1.2f,2.2f,3.2f,4.5f,5.5f };
	int arr2[20] = { 0 };

	memcpy(arr2, arr1, 5 * sizeof(float));

	return 0;
}
2、模拟实现
代码语言:javascript
复制
#include<stdio.h>

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		src = (char*)src + 1;
		dest = (char*)dest + 1;
	}
	return ret;
}
//4*3 + 3

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 40);

	return 0;
}

那么我们可不可以把1,2,3,4,5这五个整型拷贝到3,4,5,6,7这五个整型的位置(覆盖了):

下面是我们自己写的代码演示:

代码语言:javascript
复制
#include<stdio.h>
#include<assert.h>

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		src = (char*)src + 1;
		dest = (char*)dest + 1;
	}
	return ret;
}
//4*3 + 3

int main()
{
	//int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//int arr2[20] = { 0 };
	//my_memcpy(arr2, arr1, 40);

	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr + 2, arr, 20);

	return 0;
}

我们发现达不到我们想要的效果。

那索性就不要用my_memcpy了,下面是我们直接调用库里的函数实现的:

代码语言:javascript
复制
#include<stdio.h>
#include<assert.h>

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		src = (char*)src + 1;
		dest = (char*)dest + 1;
	}
	return ret;
}
//4*3 + 3

int main()
{
	//int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//int arr2[20] = { 0 };
	//my_memcpy(arr2, arr1, 40);

	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr + 2, arr, 20);

	return 0;
}

监视打开:

memcpy:不重叠的就可以了,memcpy连重叠的都能搞定。

(二)memmove的使用和模拟实现

memmove:可以处理不重叠的,也可以处理重叠内存。

代码原型:

代码语言:javascript
复制
void* memmove(void* destination, const void* source, size_t num);

三板斧——

功能: (1)memmove函数也是完成内存块拷贝的; (2)和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 注: memmove的使用也需要包含<string.h>。 参数: destination :指针,指向目标空间,拷贝的数据存放在这里; source :指针,指向源空间,要拷贝的数据从这里来; num :要拷贝的数据占据的字节数。 返回值: 拷贝完成后,返回目标空间的起始地址。

1、代码实现
(1)内存没有重叠
代码语言:javascript
复制
#include<stdio.h>
#include<assert.h>

int main()
{
	//内存没有重叠
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	//memcpy();
	memmove(arr2, arr1, 20);
}
(2)内存重叠
代码语言:javascript
复制
#include<stdio.h>
#include<assert.h>

int main()
{
	//内存重叠
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);

	return 0;
}
2、模拟实现
代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS  1

#include<stdio.h>
#include<assert.h>
void * my_memmove(void* dest,void* src,size_t num)
{
	assert(dest && src);
	void* net = dest;
	if (dest < src)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//2 3
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return net;
}
int main()
{
	//内存重叠
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr + 2, arr, 20);
	return 0;
}

二、memset、memcmp函数的使用

(一)memset函数的使用

代码原型:

代码语言:javascript
复制
void* memset(void* ptr, int value, size_t num);

三板斧——

功能: memset 函数是用来设置内存块的内容的,将内存中指定长度的空间设置为特定的内容。 注: memset 的使用也需要包含 <string.h>。 参数: ptr :指针,指向要设置的内存空间,也就是存放了要设置的内存空间的起始地址; value :要设置的值,函数将会把 value 值转换成 unsigned char 的数据进行设置的,也就是以字节为单位来设置内存块的; num :要设置的内存长度,单位是字节。 返回值:返回的是要设置的内存空间的起始地址。

1、代码实现
(1)针对字符数组
代码语言:javascript
复制
//针对字符数组
#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = "hello world";
	memset(arr + 2, 'x', 5);
	printf("%s\n", arr);

	return 0;
}
(2)针对整型数组
代码语言:javascript
复制
#include<stdio.h>
#include<string.h>

int main()
{
	int arr[10] = { 0 };
	//能否将arr的每个元素设置为1
	memset(arr, 1, 40);

	return 0;
}
2、总结

当有一块内存空间需要设置内容的时候,就可以使用memset函数,值得注意的是memset函数对内存单元的设置是以字节为单位的。

(二)memcmp函数的使用

代码原型:

代码语言:javascript
复制
int memcmp(const void* ptr1, const void* ptr2, size_t num);

三板斧——

功能: 比较指定的两块内存块的内容,比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。 注:memcmp 的使用需要包含 <string.h>。 参数: ptr1 :指针,指向一块待比较的内存块; ptr2 :指针,指向另外⼀块待比较的内存块; num :指定的比较长度,单位是字节。 返回值:

1、代码实现:
(1)比较前16个字节
代码语言:javascript
复制
#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4,8 };
	int r = memcmp(arr1, arr2, 16);
	if (r > 0)
		printf(">\n");
	else if (r < 0)
		printf("<\n");
	else
		printf("==\n");

	return 0;
}

打开内存,观察一下:

输出结果:

(2)比较17个呢
代码语言:javascript
复制
#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4,8 };
	int r = memcmp(arr1, arr2, 17);
	if (r > 0)
		printf(">\n");
	else if (r < 0)
		printf("<\n");
	else
		printf("==\n");

	return 0;
}

打开内存,观察一下:

输出结果:

2、总结

(1)如果要比较2块内存单元的数据的大小,可以使用 memcmp 函数,这个函数的特点就是可以指定比较长度; (2)memcmp 函数是通过返回值告知大小关系的。


结尾

往期回顾:

字符函数和字符串函数(二):strncpy、strncat、strncmp函数的使用、strstr的使用和模拟实现、strtok函数的使用、strerror函数的使用

字符函数和字符串函数(一):字符分类函数、字符转换函数、strlen的使用和模拟实现、strcpy的使用和模拟实现、strcat的使用和模拟实现、strcmp的使用和模拟实现

C语言指针深入详解(六):sizeof和strlen的对比,【题解】数组和指针笔试题解析、指针运算笔试题解析

结语:本篇文章就到此结束了,本文为友友们分享了C语言内存函数相关的一些重要知识点,如果友友们有补充的话欢迎在评论区留言,在这里感谢友友们的关注与支持!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、memcpy、memmove使用和模拟实现
    • (一)memcpy的使用和模拟实现
      • 1、代码演示:
      • 2、模拟实现
    • (二)memmove的使用和模拟实现
      • 1、代码实现
      • 2、模拟实现
  • 二、memset、memcmp函数的使用
    • (一)memset函数的使用
      • 1、代码实现
      • 2、总结
    • (二)memcmp函数的使用
      • 1、代码实现:
      • 2、总结
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档