目录

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

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

1、代码演示: 

(1)memcpy拷贝整型

 (2)memcpy拷贝浮点型

2、模拟实现

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

1、代码实现 

(1)内存没有重叠

(2)内存重叠

2、模拟实现

二、memset、memcmp函数的使用

(一)memset函数的使用

1、代码实现

(1)针对字符数组

(2)针对整型数组

2、总结

(二)memcmp函数的使用

1、代码实现:

(1)比较前16个字节

(2)比较17个呢 

2、总结

结尾


🔥个人主页:艾莉丝努力练剑

🍓专栏传送门:《C语言》

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平  


 


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


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

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

memcmp:memory copy——内存拷贝;

代码原型:

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拷贝字符串的,是有局限性的;

拷贝一个整型数组呢?结构体数组呢?

#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拷贝浮点型
#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、模拟实现
#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这五个整型的位置(覆盖了):

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

#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了,下面是我们直接调用库里的函数实现的:

#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:可以处理不重叠的,也可以处理重叠内存。

代码原型:

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

三板斧——

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

代码原型:

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

三板斧——

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

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

	return 0;
}
(2)针对整型数组
#include<stdio.h>
#include<string.h>

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

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

(二)memcmp函数的使用

代码原型:

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

三板斧—— 

功能:

比较指定的两块内存块的内容,比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。

注:memcmp 的使用需要包含 <string.h>。

参数:

ptr1 :指针,指向一块待比较的内存块;

ptr2 :指针,指向另外⼀块待比较的内存块;

num :指定的比较长度,单位是字节。
返回值:
1、代码实现:
(1)比较前16个字节
#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个呢 
#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语言内存函数相关的一些重要知识点,如果友友们有补充的话欢迎在评论区留言,在这里感谢友友们的关注与支持!

Logo

一站式 AI 云服务平台

更多推荐