c语言内存函数

目录

1.memcpy的使用和模拟实现

[1.1 代码演示](#1.1 代码演示)

[1.2 模拟实现](#1.2 模拟实现)

2.memmove的使用和模拟实现

[2.1 代码演示](#2.1 代码演示)

[2.2 模拟实现](#2.2 模拟实现)

3.memset的使用

[3.1 代码演示](#3.1 代码演示)

4.memcmp的使用

[4.1 代码演示](#4.1 代码演示)

1.memcpy的使用和模拟实现

复制代码
//函数原型
void* memcpy(void* destination,const char* source,size_t num);

功能:

memcpy是完成内存拷贝的,不关注内存中存放的数据是啥,一次性全拷贝

函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

如果source和destination有任何重叠,复制的结果是未定义的。(内存重叠的情况使用memmove就行)。

memcpy的使用需要包含头文件<string.h>
参数:

destination:指针,指向目标空间,拷贝的数据存放在这里;

source: 指针,指向源空间,要拷贝的数据来自这里;

num: 要拷贝的数据所占据的字节数。

返回值:拷贝完成后,返回目标空间的起始地址。

1.1 代码演示
cpp 复制代码
#include<string.h>
int main()
{
	int dest[30] = { 0 };
	int src[] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(dest, src, 20);
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", dest[i]);
	}
	return 0;
}
1.2 模拟实现
cpp 复制代码
//模拟实现memcpy
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* str, size_t num)
{
	assert(str);
	void* ret = dest;
	while (num)
	{
		*(char*)dest = *(char*)str;
		dest = (char*)dest + 1;//强制类型转换是临时的
		str = (char*)str + 1;
		num--;
	}
	return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[30] = { 0 };
	my_memcpy(arr2, arr1, 10 * sizeof(int));
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

因为memcpy函数是按照字节进行拷贝的,所以我们需要将地址转成char*类型的,这样我们就可以完成任意类型数据的拷贝。

2.memmove的使用和模拟实现

cpp 复制代码
//函数原型
void* memmove(void* destination,const void* source,size_t num);

功能:

memmove函数也是完成内存块的拷贝的,和memcpy的差别是memmove函数处理的是原内存块和目标内存块是可以重叠的。

memmove函数的使用需要包含头文件<string.h>。
参数:

destination: 指针,指向目标空间,拷贝的数据存放到这里;

source: 指针,指向源空间 ,要拷贝的数据从这里来;

num:要拷贝数据占据的字节数。

返回值:

拷贝完成后,返回目标空间的起始地址。

2.1 代码演示
cpp 复制代码
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
2.2 模拟实现

代码一:

cpp 复制代码
//模拟实现memmove
#include<assert.h>
void* my_memmove(void* dest, const void* str, size_t num)
{
	assert(dest && str);
	void* ret = dest;
	if (dest<str || (char*)dest>(char*)str + num)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)str;
			dest = (char*)dest + 1;
			str = (char*)str + 1;
		}
		return ret;
	}
	else
	{
		//后->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)str + num);
		}
		return ret;
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

代码二:

cpp 复制代码
//模拟实现memmove
#include<assert.h>
void* my_memmove(void* dest, const void* str, size_t num)
{
	assert(dest&&str);
	void* ret = dest;
	if (dest < str)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)str;
			dest = (char*)dest + 1;
			str = (char*)str + 1;
		}
		return ret;
	}
	else
	{
		//后->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)str + num);
		}
		return ret;
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

3.memset的使用

cpp 复制代码
//函数原型
void* memset(void* ptr,int value,size_t num);

功能:
memset函数是用来设置内存块的内容的,将内存中指定长度的空间设置为特定的内容,是以字节为单位来设置的。

memset函数的使用需要包含头文件<string.h>。
参数:

ptr:指针,指向要设置的空间内存,也就是存放了要设置的内存空间的起始地址;

value:要设置的值,函数会把value值转换成unsigned char的数据进行设置, 也就是以字节为单位来设置内存块的

num:要设置的内存长度,单位字节。

返回值:返回要设置的内存空间的起始地址。

3.1 代码演示
cpp 复制代码
#include<string.h>
int main()
{
	char str[] = "helloworld";
	//现在我想将这个字符串全换成h
	memset(str, 'h', 10);
	printf("%s\n", str);
	return 0;
}

提醒:我们想将str10={1,2,3,4,5,6,7,8,9,10};这个数组中的数字全置为1,通过memset函数是不可能完成的,这是因为memset函数是按照字节来设置的,它会将每个字节都设置为1

4.memcmp的使用

cpp 复制代码
//函数原型
int memcmp(const void* ptr1,const void* ptr2,size_t num);

功能:

比较指定的两块内存块的内容,比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。memcmp函数是一对字节一对字节往后比较。

memcmp需要包含头文件<string.h>。
参数:

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

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

num:指定的比较长度,单位是字节。

返回值:

4.1 代码演示
cpp 复制代码
#include<string.h>
int main()
{
	char arr1[] = "hello world";
	char arr2[] = "hello bit";
	int ret=memcmp(arr2, arr1,5);
	if (ret > 0)
		printf(">");
	else if (ret < 0)
		printf("<");
	else
		printf("==");
	return 0;
}
相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
克里斯蒂亚诺更新5 小时前
ruoyi角色权限的对应关系
笔记
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117767 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大8 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai9 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang