【C语言基础】内存相关的函数

目录

引入

基本介绍 

一. memcpy 内存拷贝函数

1. 基本介绍

 2. 使用细节

3. 模拟实现

二. memmove 内存移动函数

1. 基本介绍

2. 使用细节

3. 模拟实现

三. memset 内存设置函数

1. 基本介绍

2. 使用细节

四. memcmp 内存比较函数

1. 基本介绍

2. 使用细节


引言

我们之前学过strcpy, strcmp, strcat ,strncpy 等和字符串相关的函数,这些函数的操作对象是字符串和\0,我们无法直接用这些函数完成对浮点型,整型,结构体等类型的数据进行这类操作,这时我们就需要使用到内存相关的函数

基本介绍 

  • 内存相关的函数主要是针对内存块的,可以处理任意类型的数据
  • 操作数据时是以字节为单位进行操作的

内存相关的函数可以接收任意类型的指针(void*),然后其强制转换成字符型指针,再通过一个字节一个字节地操作,最后完成对整个数据的操作

  • 使用要包含头文件 string.h

一. memcpy 内存拷贝函数

1. 基本介绍

void * memcpy ( void * destination, const void * source, size_t num );
  • memcpy函数作用:只要是放在内存里的数据,就都可以进行拷贝
  • 返回的值:返回的是目标空间的起始地址  
  • 形参列表分别对应:目标空间的地址,源空间的地址,要拷贝的字节个数

函数的使用

#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	//将arr1中的3,4,5,6,7拷贝放到arr2中
	memcpy(arr2, arr1 + 2, 20);//拷贝5个整型--20字节

	for (int i = 0; i < 10; i++)
	{
       printf("%d ", *(arr2 + i));
	}
    //输出结果3 4 5 6 7 0 0 0 0 0
	return 0;
}

 2. 使用细节

  • 形参列表中的第三个参数指的是要拷贝的字节个数
  • memcpy函数不负责重叠内存的拷贝

比如 int arr1[ ] = {1,2,3,4,5,6,7},

不能使用memcpy函数将arr1里面的1, 2, 3,4拷贝到 arr1 里的3, 4, 5, 6位置上

原因:当把 1 拷贝到 3 的位置上后,数字3就被覆盖了;当把 2拷贝到 4 的位置上后,数字4就被覆盖了,此后就一直循环拷贝 1, 2

3. 模拟实现

思路:

  1. 记录目标空间的起始地址(用于最后返回)
  2. 强转为字符型指针,原因:void*类型的指针不能进行解引用操作,也不能进行加减运算
  3. 循环赋值/拷贝
#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);//强转为字符型指针
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;//返回目标空间的起始地址
}

二. memmove 内存移动函数

1. 基本介绍

void * memmove ( void * destination, const void * source, size_t num );
  • memmove函数作用:负责重叠内存的拷贝 
  • 返回的值:返回的是目标空间的起始地址  
  • 形参列表分别对应:目标空间的地址,源空间的地址,要拷贝的字节个数

 函数的使用

#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);//将1,2,3,4,5拷贝到3,4,5,6,7处
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(arr1 + i));
	}
	//输出结果:1,2,1,2,3,4,5,6,7,8,9,10
	return 0;
}

2. 使用细节

  • 形参列表中的第三个参数指的是要拷贝的字节个数
  • C语言标准规定,memcpy只要能实现不重叠的拷贝就行,重叠的拷贝由memmove实现

      在VS上memcpy可以实现重叠内存的拷贝,但在其它编译器上不保证能实现

3. 模拟实现

思路:

1.记录目标空间的起始地址
2.强转为char*类型
3.分情况拷贝
  情况1:当源的起始地址小于目的地的起始地址时,从后往前拷贝 
  情况2:当源的起始地址大于目的地的起始地址时,从前往后拷贝
  原因:数组随着下标的增长,地址是由低到高变化的
4.返回目标空间的起始地址

#include<assert.h>
void* my_memmove(char* dest, char* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	if (src < dest)//从后往前拷贝
	{
		while (num--)
		{
			*((char*)dest + num ) = *((char*)src + num);
		}
	}
	else//从前往后拷贝
	{
		while (num--)
		{
			*((char*)dest) = *((char*)src);
			dest = ((char*)dest) + 1;
			src = ((char*)src) + 1;
		}
	}
	return ret;//返回目标空间的起始地址
}

三. memset 内存设置函数

1. 基本介绍

void * memset ( void * ptr, int value, size_t num );
  • memset函数是用来设置内存的,可以更改内存块中任意类型的数据
  • 返回类型:返回的是目标空间的起始地址
  • 形参列表分别对应:从哪开始设置内存块,设置成什么内容,总共要设置几个字节

函数的使用1

#include<string.h>
int main()
{
	char arr[] = "hello world";
	memset(arr + 6, '*', 5);
	printf("%s\n", arr);
	//输出结果 hello *****
	return 0;
}

 函数的使用2

#include<string.h>
int main()
{
	int arr[10] = { 0 };
	memset(arr, 1, 10);//改前10个字节为1
	//arr中前10个字节 01 01 01 01  01 01 01 01  01 01 
	//arr中的数值为 16843009 16843009 257 0 0 0 0 0 0 0 
 	return 0;
} 

2. 使用细节

memset函数设置内存时是一个字节一个字节进行设置的

四. memcmp 内存比较函数

1. 基本介绍

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • memcmp函数作用:用于比较两个内存块的大小
  • 返回的值:在前 num 个字节中,若ptr1指向的内存大于num2指向的内存,则返回大于0的数字;若ptr2指向的内存小于num2指向的内存,则返回小于0的数字;若ptr2指向的内存等于num2指向的内存,则返回0
  • 形参列表对应:内存块1,内存块2,要比较的字节个数

函数的使用

#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3 ,6,5};
	int ret1 = memcmp(arr1, arr2, 12);//返回0
	int ret2 = memcmp(arr1, arr2, 13);//返回小于0的数字
	
	return 0;
}

arr1在内存中的存储对应 0x 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00  

arr2在内存中的存储对应 0x 01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00 05 00 00 00  

2. 使用细节

  • 函数的第三个参数表示:要比较的字节个数
  • 注意超过一个字节的数据在内存中存储的顺序是怎样的
  • 28
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值