Skip to content

指针(2)

1527字约5分钟

2024-07-07

67.动态内存分配

//输入学生数,再输入每个学生对应的姓名和成绩,最后把这些信息输出
#include <stdio.h>
#include <stdlib.h>   //有nalloc calloc free exit的函数声明
#include <malloc.h>   //alloc calloc free
int main(void)
{
	int n;
	printf("请输入学生数:");
	scanf("%d",&n);
//	void *malloc(unsigned int size):其功能是在堆区分配连续的size个字节的存储空间并且返回这段存储空间开头的地址,如果内存分配失败,会返回空指针
	int *p1=(int *)malloc(sizeof(int) *n);       //强制数据类型转换可以省略
	if(p1 ==NULL)                                //判断是否是空指针
	{
		printf("内存分配失败,程序退出\n");
	exit(-1);
	}
	//void *calloc(unsigned int n,unsigned int size);
	char (*p2)[50] =(char (*)[50])calloc(n,sizeof(char)*50);
	if(p2 ==NULL)
	{
		printf("内存分配失败,程序退出\n");
	exit(-1);
	}
	for(int i=0;i<n;++i)
	{
		printf("请输入第%d个学生的成绩和姓名:\n",i+1);
		scanf("%d%s",p1+i,p2[i]);
	}
	for(int i =0;i<n;++i)
	{
		printf("%d个学生的成绩为%d,姓名为%s",i+1,p1[i],p2[i]);
		puts("\n");
	}
	//void free(void *p);
	free(p1);                                    //释放动态存储空间
	free(p2);
	return 0;
}

68.1realloc函数

/*
1,创建一段动态内存空间,存放两个整型数据
2.对这段动态内存空间进行扩容,然后再存放两个整型数据,再把这4个整型数据输出
3.用这段动态内存空间存放两个double型数据,最后输出两个double型数据
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
//	int *p=malloc(sizeof)(int)*2);   error 因为程序实际上是一个c++程序,在c++中可以把一个其他类型的指针赋给一个void指针变量,反之程序就会出错
	int *p=(int *)malloc(sizeof(int)*2);
	if(p == NULL)
	{
		printf("内存分配失败,程序退出\n");
		exit(-1);
	}
	p[0]=1;
	p[1]=2;
	printf("%d,%d\n",p[0],p[1]);
	//void *realloc(void *p,unsigned int size);   //其功能是吧p所指向的动态存储内存空间改成size个字节,如果不成功则返回一个空指针
	if(realloc(p,sizeof(int)*4) == NULL) //stdlib.h和malloc.h都有realloc的函数声明,其指针参数必须是以个已经指向了一段动态内存空间的指针
	{
		printf("内存分配失败,程序退出\n");
		exit(-1);
	}
	p[0]=1;
	p[1]=2;
	p[2]=3;
	p[3]=4;
	printf("%d,%d,%d,%d\n",p[0],p[1],p[2],p[3]);
	double *p1=(double *)p;
	p1[0]=3.14;
	p1[1]=69.3;
	printf("%lf,%lf\n",p1[0],p1[1]);
	return 0;	
}

68.2.动态内存空间存储信息

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int n;
	printf("请输入学生数:");
	scanf("%d",&n);
	char *a = (char *)malloc(62*n);
	if(a == NULL)
	{
		printf("内存分配失败,程序退出\n");
		exit(-1);
	}
	for(int i = 0;i<n;++i)
	{
		printf("请输入第%d个学生的姓名,年龄和成绩:\n",i+1);
		scanf("%s%d%lf",a+62*i,(int *)(a+50+62*i),(double *)(a+54+62*i));
	}
	for(int i = 0;i<n;++i)
	{
		printf("%d个学生的姓名:%s年龄:%d成绩;%lf\n",i+1,a+62*i,*(int *)(a+50+62*i),*(double *)(a+54+62*i));
	}
	free(a);
	return 0;
}

69.free和realloc函数

#include <stdio.h>
#include <stdlib.h>
void f(void)   //free函数的注意事项
{
	int *p = (int *)malloc(sizeof(int)*10);
	if(p == NULL)
	{
		printf("分配内存失败,程序退出\n");
	}
//	free(p+1); 1. error free函数的实参必须是一个动态空间的首地址或者空指针
	free(p);   //2.如果分配的动态内存空间不人为释放,将在程序结束后,系统收回
	p= NULL;  //3.free函数对值为NULL的指针操作多次,程序不会报错,可以有效的避免野指针
	free(p);  //4.在堆区有两个动态内存A和B(A前B后),p1和p2分别指向他们,如果free(p1);不会把B的内存空间释放掉,因为在堆区不存在2段连续的动态内存空间,即使有free(p1)对B的动态内存空间也没有影响
}
	void g(void)  //realloc函数注意事项
	{
		//1.realloc重新分配动态内存成功的话,会返回该动态内存空间的首地址,否则返回空指针
		int *p=(int *)realloc(NULL,sizeof(int)*4);  //2.如果realloc的指针实参为NULL,则会开辟新的动态内存空间。
		if(p == NULL)
		{
			printf("分配内存失败,程序退出\n");
			exit(-1);
		}
		for(int i = 0;i<4;++i)
			p[i]=i;
		printf("地址为%p\n",p);
		/*
		printf("地址为%p\n",realooc(p,1000)); //3.realloc对一段动态内存空间扩容的时候,会根据其后是否有足够d连续的未被其他程序的空间来选择扩容的方式,如果有,会直接扩容,并把指针实参的值返回,如果没有,则会开辟新的动态内存空间,将原有的动态内存空间的数据拷贝到新的动态内存空间并把原来的动态内存空间释放掉,最后返回新的动态内存空间的首地址
		free(p);  4.error因为在该句被运作之前,p指向的动态内存空间已经被释放,p成了一个野指针
		*/
		printf("地址为%p\n",p=realloc(p,1000)); //5.使用realloc函数时,把函数返回值赋给它的指针实参,有效防止野指针
		realloc(p+1,4);      //6.error realloc函数的指针必须是一个动态内存空间的首地址或者空指针
		printf("%p\n",realloc(p,0));   //7.如果realloc函数所分配的大小为0个字节,则等价于free(p);其返回值为NULL 
	}
int main(void)
{
	f();
	g();
	return 0;
}

70.指针小结

指针就是地址,地址不仅有值,而且有数据类型 指针指向变量的意思是通过指针我们可以访问这个变量。 指针P指向数组元素时,这个元素的上一个元素的地址是p-1,下一个元素的地址是p+1; 如果p1和p2指向的元素同属一个数组的,那么[p1-p2]就代表这两个元素下表差,而[p1+p2]毫无意义