内存函数和动态内存管理

目录

 memcpy(string.h)

memcpy 的模拟实现

memmove (string.h) 

动态内存管理函数

malloc (stdlib.h)

free(stdlib.h)

calloc(stdlib.h)

 realloc(stdlib.h)

使用动态内存常见错误 


 memcpy(string.h)

        注:void* 可以接收任意类型的指针  

void *destination:目标数组地址 转为 void* 类型的指针。

const void * source :被复制的的数组地址,转为 const void *类型表示不能被修改。

size_t num :需要拷贝的字节数(你打算拷贝多少个字节的内容)。

     

作用:复制内存块

        将源地址内容按照 给定大小的 num 个字节内容 拷贝至目标地址,

        该函数不检查中的任何终止 null 字符 - 它总是准确复制 num 个字节。

        \t 表示制表符 tab 也就是d后面的4个空格

        拷贝是完全拷贝了滴,只不过打印的时候用的%s遇见\0就停止以才是这个结果

        为避免溢出,目标参数和参数所指向的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[20] = { 0 };
	char arra[20] = "sjd	f\nh i\0asufhdi";
	
	memcpy(arr, arra, 15);
	printf("%s\n", arr);
	

	return 0;
}

memcpy 的模拟实现

循环里面的代码也可以用 

        des 和 sou 代替

void* Mymemcpy(void* destination , const void* source , size_t num)
{
#if 0;
	char* des = (char*)destination;
	char*sou = (char*)source;
#endif
	(char*)destination;
	(char*)source;
	while (num--)
	{
		*(char*)destination = *(char*)source;
		((char*)destination)++;//后置++优先级最高,所以要用括号哦括起来这个强制类型转换
								//否则会认为先++后强制类型转换
	     ((char*)source)++;
	}
	//return destination;
}

int main()
{
	int arr[15] = { 1,2,3,4,5,6,7,8,9,10 };
	int arra[15] = { 0 };
	Mymemcpy(arra,arr,(sizeof(arr[1])*10));
	


	return 0;
}

memmove (string.h) 

void *destination:目标数组地址 转为 void* 类型的指针。

const void * source :被复制的的数组地址,转为 const void *类型表示不能被修改。

size_t num :需要拷贝的字节数(你打算拷贝多少个字节的内容)。

作用:移动内存块(允许重叠)

        将 num 字节的值从指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,从而允许目标重叠。

        指针和目标指针所指向的对象的基础类型与此函数无关;结果是数据的二进制副本。

        该函数不检查中的任何终止 null 字符 - 它总是准确复制 num 个字节。

        为避免溢出,目标参数和参数所指向的数组的大小应至少为 num 个字节

 默认,des 和soure 指向的同一块空间,绿色为soure 起始地址黄色为des起始位置

        如果我们想要挪动,就需要先挪最后一位,依次递减挪动,先挪5再432,如果先挪2到4那么4就被修改,就不能达到效果

反之起始位置大于目标地址,那么就从头开始挪动

void* mymemmove(void* des, void* soure, size_t n)
{
	int i = 0;
	void* ret = des;
	if (des > soure)
	{
		while (n--)
		{
			*(((char*)des)+n) = *(((char*)soure)+n);
		}
	}
	else
		while (i<n)
		{
			*((char*)des)++ = *((char*)soure)++;
			i++;
		}
	return ret;
}
int main()
{
	int arr[] = { 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9, };
//arr+3,arr,20    1 1 2 2 1 1 2 2 3  
		//		  3 3 4 4 5 3 4 4 5 5 
	mymemmove(arr, arr+4, 20);
	for (int i = 0; i < 17; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

动态内存管理函数

malloc (stdlib.h)

作用 :开辟一块动态内存空间

返回值:
        • 如果开辟成功,则返回⼀个指向开辟好空间的指针。
        • 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查
         返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使时由你自己决定需要它是什么类型

         我这里没有释放空间,不建议模仿,这里因为程序结束会回收,所以问题不大,因为代码短不会影响到后面。
        一定要记得判断空间是否开辟成功
int main()
{
	//开辟5个整形的空间
	int* p = (int*)malloc(sizeof(int) * 5);
	if (p == NULL)
	{
		perror(malloc);
		return EOF;
	}
	int i = 0;
	for (i; i < 5; i++)
	{
		*p = i;
		printf("%d ", *p);
		p++;
	}
	return 0;
}

free(stdlib.h)

作用:

        用来释放掉动态内存函数开辟的空间

切记:

        ptr 一定要指向那块空间的起始位置,否则就是不完全释放后面可能会出现泄露

        如果你乱给指针,那么free函数也是乱来的

        如果是空指针没有操作

代码建议:

        每次使用指针变量接收完地址后,建议拷贝一份,什么操作都用拷贝的变量区执行,最后free(p)  ,p为接收开辟的地址的变量

int main()
{
	//开辟5个整形的空间
	int* p = (int*)malloc(sizeof(int) * 5);
	int* ret = p;
	if (p == NULL)
	{
		perror(malloc);
		return EOF;
	}
	int i = 0;
	for (i; i < 5; i++)
	{
		*ret= i;
		printf("%d ", *ret);
		ret++;
	}
	free(p);
	return 0;
}

calloc(stdlib.h)

作用:

        开辟一块空间

参数:

        size_t num 元素个数

        size_t size 每个元素的类型

返回值:

        开辟成功返回地址

        失败返回 NULL 

        calloc 会把每个字节初始化为0,而malloc 不会。

 realloc(stdlib.h)

作用:

        更改 ptr 所指向的空间大小

参数:

        ptr 需要被修改空间的地址(只能增加)

        size 为扩容后总空间大小

返回值:

        原有空间的后面足够分配的情况,返回原地址(ptr)

        原有空间的后面不够配的的情况,在堆上另找一块空间并且会拷贝原空间的内容,再返回新地址

        NULL表示开辟失败,不会有其他操作,ptr 的内容还在

        

使用动态内存常见错误 

1 对NULL指针的解引⽤操作

2 对动态开辟空间的越界访问
3 对⾮动态开辟内存使⽤free释放
4 使⽤free释放⼀块动态开辟内存的⼀部分
5 对同⼀块动态内存多次释放
6 动态开辟内存忘记释放(内存泄漏)
忘记释放不再使⽤的动态开辟的空间会造成内存泄漏。
切记:动态开辟的空间⼀定要释放,并且正确释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值