C语言内存函数

### 这里主要介绍memcpy  和  memmove 的原理和模拟以及 memcmp 、memset的基本用法。

它们的头文件都是string.h

C语言内存函数操作的是内存,也就是通过地址去操作,所以此类函数操作的对象相当广泛,了解学习有关的基本知识会对我们很有帮助。

## memcpy

对于内存函数我们可以通过联想到一些字符串函数来理解学习,不同的是内存函数操作的是地址,所以不限制形参的类型,而字符串函数只能对字符串进行相关操作;

解释:这个函数返回类型是void* ,前两个参数也是void* ,原因:void* 可以接收任何类型的指针;第一个参数是“目的地”,第二个参数是“来源”,含义是从source里面copy的内容将放到destination里面去,最后一个参数指明了操作的字节个数(注意:无论指针指向的元素是什么类型的,这个函数都是一个字节一个字节去操作草拷贝的)

示例

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);//将arr2里面的5个整型数据拷贝到arr1里面。
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

值得说明的是:当你操作的两个数组里面的元素有内存重叠(地址一样)的时候,使用这个函数最终得到的结果是未定义的,为了避免,我们使用另一种内存函数,下面来介绍。

## memmove

这个函数和memcpy几乎无异,唯一不同的是这个函数可以操作内存重叠的元素

示例

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr, arr + 2, 20);//我们将3,4,5,6,7往1,2,3,4,5的位置copy的时候有内存重叠
	int i = 0;
	for (; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

### memcpy和memmove的模拟实现

memcpy模拟

void* my_memcpy(void* arr1, const void* arr2, size_t num)
{
	assert(arr1 && arr2);
	void* ret = arr1;
	int i = 0;
	
		for (i = 0; i <num; i++)
		{
			*((char*)arr1) ++ = *((char*)arr2) ++;//一个字节一个字节copy,++后置,每次换完再完后跳一个字节
		}
	
	return ret;
}
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5 };
	my_memcpy(arr1, arr2, 20);
	int len = sizeof arr1 / sizeof arr1[0];
	for (int i = 0; i <len; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

memmove 

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest <= src)
	{
		while (num--)
		{
			*((char*)dest)++ = *((char*)src)++;
		}
	}
	else if (dest > src)
	{
		while(num--)
		{
			*(((char*)dest) + num) = *(((char*)src) + num);
		}
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1+3,arr1 ,20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

解释my_memmove里面的选择语句:我们已经知道,memmove无视内存的重叠,我们要想出一种办法保证copy的时候内存不会重叠;如果dest地址比src大,那么src指向的数组就要从后往前copy,看到上面代码,此时dest>src,如果从前往后(也就是依次把1、2、3、4、5copy到4、5、6、7、8)我们会发现当1、2、3copy完的时候,原本4、5、6变成了1、2、3,这一部分正确,但是本是要被copy的4、5变成了1、2,这时候就7、8的位置就变成了1、2而非4、5,最后得到的结果是:1,2,3,1,2,3,1,2,9,10;而不是1,2,3,1,2,3,4,5,9,10;所以我们要从后往前,也就是把5,4,3,2,1依次copy到8、7、6、5、4的位置;

如果dest<src,那么反之同理。

### memcmp和memset

memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。
#include <stdio.h>
#include <string.h>
int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

memcmp参照strcmp理解

 

⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节,但凡有一个字节里的数的大小更大,这个函数的比较就完成,num表示了从指向的那个地址的字节开始,向后比较多少个字节;

 

简单示例

 

#include <stdio.h>
#include <string.h>
int main()
{
	int str1[] = { 1,2,3,4,5 };
	int str2[] = { 1,2,3,5,6 };
	int ret = memcmp(str1, str2, sizeof(str1));//比较整个
	printf("%d\n", ret);
}

                                                                                                                                         ————完

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值