动态数组学习心得

#include "stdio.h"
#include <__msvc_all_public_headers.hpp>
typedef struct
{
	int* array;
	int length;
}Darray;
Darray create(int n)
{
	Darray a;//定义了结构类型Darray下的一个结构  a
	int i;
	a.array = (int*)malloc(sizeof(int) * n);
	/*
	申请了堆里面的内存 ,并将堆内存的首地址给了a结构里面的array项,
	实现了不同函数之间的通信
	
	*/if (a.array == NULL)
		return NULL;
	else
	{
		a.length = n;//当申请的对内存不为空时,将n赋值给结构a的数据项
		for (i = 0; i < a.length; i++)
			scanf_s("%d", &a.array[i]);
	}
}
return a;

void  grow(Darray* aPtr, int n)//让数组的长度翻倍
{
	int* p;
	int i;
	p = (int*)malloc(sizeof(int) * n);//申请一个堆中的内存块,让局部指针p指向内存块的首地址
	if (p == NULL)//检验这个内存块是否为空
		return;
	else
	{
		for (i = 0; i < aPtr->length; i++)//在对指向结构体的指针的使用时要处理引用问题
			p[i] = aPtr->array[i];//将原来的数据放到新的那个数组中来
		for (i = aPtr->length; i < n; i++)
			scanf_s("%d", &p[i]);
		free(aPtr->array);
		aPtr->array = P;//更新指针域
		aPtr->length = n;//更新数据域
	}
}

void print(Darray* p)//输出更新之后的数组
{
	int i;
	for (i = 0; i < p->length; i++)
		printf("%d", p->array[i]);
	return;
}
//在使用指向结构体的指针时,结构体名字 *指针名字
//引用结构体中的元素时   p->结构体中的小项就行
void release(Darray* p)
{
	free(p->array);//注意对于那种使用malloc 定义的内存区域才需要进行释放
}
int main()
{
	Darray a;
	scanf_s("%d", &n);
	a = create(n);
	print(&a);
	grow(&a, n * 2);
	print(&a);
	release(&a);
	return 0;
}
/*
内存使用问题
编译器看不到,在使用的时候就看到了
1:内存还未分配成功就进行使用(在处理动态内存时
措施:在使用内存之前先检查指针是否为空指针
例如:p=(int *)malloc(n*sizeof(int ))
if (p==NULL){
	printf ("No  enough  memory!\n");
	exit(1);//可以直接将这条程序杀死
	}
	注意如果在一个函数中进行动态内存的分配时;
	void  Fun (void )
	{
		p=(int *)malloc(n*sizeof(int 
		if (p==NULL);
			return ;//当为空指针时,直接将函数进行返回
		}
但是在函数中如果多出进行了动态内存的申请时,在返回之前必须将之前申请的动态内存全部释放
防止出现内存泄漏
在调试中进行
void Fun (int *p)
{
	assert(p!=NULL);
	}

2:内存分配成功但是尚未初始化就当成右值进行使用(以为内存的初始值为0)
//静态,外部数组的初始值为0
措施,,
即使初始值为0,也不要忘记进行初始化
对于malloc(申请长度)动态分配的内存,,最好用memset()进行清零操作//怎么用?
对于指针变量,即使后面有对其进行赋值的语句,也最好在定义的时候将其初始化为NULL
3:内存成功,,操作越界
例如  对于数组进场下标多一或者少一
在使用malloc 申请动态空间时
p=(int *)malloc(n*2)当这n个元素的字节数比2大的时候,,在后期的写入中极有可能出现越界
措施  
1:在处理数组下标的时候,,用循环语句遍历n个元素时,注意下标从0开始,到n-1结束
2:计算动态内存的字节数的时候,始终用sizeof 运算符
3:使用strcpy(),   gets(),   memcpy()   时小心第三个咋用?
关于第三个
char  a[100],b[50];
memcpy(b,a,sizeof(b));将数组a的前50个字节给b
要的
但是!!!!!
memcpy(b,a,sizeof(a));//越界访存
第四种
释放了内存,但是继续进行使用它
起因:用free 释放指针指向的内存以后,没有立即将指针设为NULL,导致产生悬空指针,,就是野指针
指向无效内存;if语句对空指针起作用,对野指针就不行
因为在free释放了内粗以后,,,指针的值是地址,,不变的,只是这块内存不能再被程序进行访问了

例如:
free(p);//表示程序对p指向的内存部分不再拥有控制权
if (p!=NULL)//并不会改变p的值
{
strcpy(p,"def");//试图修改已经释放的内存
}
野指针实际例子1,,当多个指针指向同一内存块时
char *p,*q;
p=(int *)malloc(256);
q=p;
free(p);
if (q!=NULL)//不起作用,对也指针
{
strcpy(q,"def");//试图修改已经释放的内存,,家都没了,,钥匙不存在哈
}
对策,,,将free集中在函数的入口处
不行,,在释放内粗以后马上,,将其令为空指针
野指针实际例子2:
函数的return 语句返回了不该返回的内存地址
char *p(void)
{
char s[20];
scanf_s("%s",s);
puts(s);
return s;
}不要返回局部变量哈,不能对空指针进行写入哈
在处理从函数中返回动态分配的内存的地址。。使用二级指针
因为使用一级指针作为形参时,它只是一个局部变量而已,,在函数结束时就被拿走了,
但是使用二级指针就不会出现这样的效果。

可以用return 返回动态地址(只能一个
第五种
忘记释放内存,造成内存泄漏
用free处理
从函数返回之前一定要释放垃圾(已经成功申请的堆
在分配了内存之后,有丢失了对这块内存的追踪路径
1:用realloc函数调整内存块的大小失败时并返回NULL
2:调整指针指向的内存块时
例如p1指向了堆	A
p2指向了堆B
p2=p1//让两个指针都指向了堆A,此时无法进行堆B的访问,,B泄漏
3:误以为指针消亡了,它所指向的内存就自动释放
例如:
void Fun (void)
{
	char *p=(char *)malloc(256);
}//在次函数结束之后虽然p是一个局部变量,它在程序结束后被释放了但是p指向的内容并没有。。
局部变量p在栈,,p值在堆
指针的消亡并不代表它所指向的内存会被自动释放
注意不要重复释放,,在多个指针指向了同一内存块
自动变量比较好,,,malloc

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值