内存函数的介绍

前言:

本博客向大家介绍四个内存函数:memcpy(内存拷贝)、memmove(内存移动)、memcmp(内存比较)、memset(内存设置)

memcpy函数的介绍及其应用:

  1. num表示要拷贝几个字节

  2. 遇到'\0'他并不会停下来

  3. 如果destination和source有任何的重叠,复制的结果都是未定义的

  4. 不管是什么数据类型,它都能来;strcpy只能针对字符串

  5. VS2019编译器中memcpy可以实现重叠拷贝(尝试一下就可以发现),不能保证所有的memcpy都能做到VS2019里的一样可以实现重叠拷贝

  6. C语言规定:
       memcpy只需要不重叠的拷贝就ok
       memmove是需要实现重叠内存的拷贝

  7. memcpy的头文件是:#include <string.h>


memcpy的应用:

#include <stdio.h>
#include <string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);//拷贝5个整型进去,因为num的单位是字节,所以此时num的值是5*4=20

	float str1[] = { 1.0f,2.0f,3.0f,4.0f };//如果不写f编译器会把他当成double类型的数据
	float str2[5] = { 0.0 };
	memcpy(str2, str1, 8);
	return 0;
}

效果:

遇到'\0',并不会停止拷贝:


memcpy的模拟实现:

memcpy函数的设计:void* memcpy(void* destination, const void* source, size_t num);

思路:

格式:既然是模拟,格式应该尽量一模一样。memcpy函数可以接收任何类型的数据,所以模拟的时候要设计成void* 类型。另外,memcpy函数在C语言中是不处理重叠的数据的,因此本次模拟实现也无法处理模拟重叠的数据,即只能处理src与dest无重叠部分的情况

拷贝:因为memcpy函数是以字节为单位进行拷贝的,所以我们在对数据进行处理的时候要先将其强制类型转换成char*类型,以便以字节为单位进行操作

#include <stdio.h>
#include <assert.h>

//因为memcpy是什么数据类型都能使用的,所以两个参数不应该弄成int或者是char或者是其他的
//应该弄成void 
//只有void才可以接收一切的数据类型
void* my_memcpy(void* dest, void* src, size_t num)
{
	assert(src);
	void* ret = dest;
	while (num--)//一次拷贝一个字节,要拷贝num个字节,所以是num--
	{
		*(char*)dest = *(char*)src;
		//先把dest和src都强制类型转换成char类型的指针
		//一方面是因为void类型的指针不能直接拿出来使用
		//一方面是为了一次只拿一个字节的内容
                
                //error的写法:
				//(char*)dest++;
				//(char*)src++;
					//先使用强制类型转换
					//再加加
					//但是此时强制类型转换已经没有用了
					//相当于白费了
                    
                    //error的写法:
					//((char*)dest)++;
					//((char*)src)++;
					//将强制类型转换及其的使用对象括起来
					//使得其对强制类型转换以后的结果进行加加
					//这种写法在有的编译器里能行
					//但是不是所有

		dest = (char*)dest + 1;
		src = (char*)src + 1;
        //向后挪的表示方法
		//这种写法在任何编译器上都能跑
	}			
	return ret;
}

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

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

效果:



memmove函数的介绍及其应用:

  1. memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠。如果源空间和目标空间出现重叠,就得使用memmove函数处理
  2. memmove的头文件:#include <string.h>

memmove的应用:

include <stdio.h>
#include  <string.h>

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memmove(arr2, arr1, 20);//拷贝5个整型进去,因为num的单位是字节,所以此时num的值是5*4=20

	float str1[] = { 1.0f,2.0f,3.0f,4.0f };//如果不写f编译器会把他当成double类型的数据
	float str2[5] = { 0.0 };
	memmove(str2, str1, 8);
	return 0;
}

效果:


memmove的模拟实现:

memmove函数的设计:void* memmove( void * destination, const void * source,size_t num);

思路:memmove函数比memcpy函数多处理重叠拷贝的情况(dest和src有重叠的部分)

 画图把所有的情况分析清楚,然后结合上面memcpy函数的模拟实现来改良优化即可。

#include <stdio.h>
#include <assert.h>

void* my_memmove(void* dest, void* src, size_t num)
{
	assert(src);
	void* ret = dest;
	if (dest < src)
	{
		while (num--)//从前向后的
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//后到前
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

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

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

效果:


memcmp函数的介绍及其应用:

memcmp函数的设计:int memcmp(const void* ptr1, const void* ptr2, size_t num);

  1. 比较的是ptr1和ptr2指针开始的num个字节(注意num的单位是字节哦)
  2. ptr1<ptr2--->返回一个小于零的数;ptr1>ptr2--->返回一个大于零的数;ptr1==ptr2--->返回0
  3. void*又暗示着参数可以是任意类型
  4. strncmp只能比较字符串的大小;而memcmp可以比较任意类型
  5. memcmp的头文件是:#include <string.h>

memcmp的应用:

#include <stdio.h>
#include <string.h>

int main()
{
	int arr[] = { 1,2,3,4,5 };
	int str[] = { 1,2,3,7 };
	int ret = memcmp(arr, str, 16);
	printf("%d\n", ret);
	return 0;
}

效果:



memset函数的介绍及其应用:

memset函数的设计:void* memset(void *ptr, int value,size_t num);

  1. 内存设置:设置ptr(要设置的内存块)处的内存,将其设成value值,num个字节
  2. memset的头文件是:#include <string.h>

memset的应用:

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5 };
	memset(arr, 0, 12);
	//也可以通过调试来看
	//调试可以更加直观地观察到改变的是字节

	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

效果:



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值