【C语言】经常容易混淆的指针 动态内存分配 内存泄漏 易错的内容

 1.经常容易混淆的指针
        1.int *a[10];
        这是一个指针数组,数组a中有10个整型的指针变量(常用语保存多个字符串)

int a,b,c;
int *pa[3]; //指针数组pa,每个元素可以存储的是地址 
pa[0] = &a;  //元素0保存的是变量a的地址 
pa[1] = &b;
pa[2] = &c;

  2.int (*a)[10]
        这是一个数组指针,常用于定义一个行指针,用于保存二维数组的地址;二维数组的形参可以定义为数组指针变量。

int (*a)[10];
int arr[2][3] = {0};
a = arr;     //数组指针a,指向二维数组arr

如果它加1的话,指向二维数组的下一行的行首地址。

3.int **p; 

      这是一个指针的指针,保存指针变量的地址,也称二级指针;搭配指针数组使用。

//经常容易混淆的指针
#include<stdio.h>

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int **p;//定义一个二级指针
	int *q[10];//定义一个指针数组,数组中的每一个元素是一个指针
	int i;
	for(i=0;i<10;i++)
	{
		q[i] = &arr[i];
	}
	p = &q[0]; 
	printf("%p\n",p);
	printf("%p\n",q[0]);
	printf("%p\n",*p);
	printf("%p\n",++p);
	printf("%p\n",q[1]);
	return 0;
}

        2.只读指针变量

int a = 100;
int b = 200;
int * const p = a;   //只读指针变量     const修饰的是*,即指针变量不能变

*p = 300;  //正确,指针所指向的内容可以改变

 p = &b;//错误,指针的指向标不可以改变,即指针的值不能改变

2.只读变量指针

int a = 100;
int b = 200;
int * const p = a;   //只读指针变量     const修饰的是int,即数据变量不能变

*p = 300;  //错误,指针所指向的内容不可以改变

 p = &b;//正确,指针的指向标可以改变,即指针的值能改变

3.1.int *f(void);
    注意:f没有用括号括起来,说明f是一个函数,*修饰返回值类型,因此是指针函数。他是一个函数的声明,声明这个函数的返回值为int *类型的。
    2.int(*f)(void);
        注意:*f用括号括起来了,*修饰f说明,f是一个指针变量,因此是函数指针。f是个函数指针变量,存放函数的地址,他指向的函数必须有一个int类型返回值,没有参数。

2.动态内存申请
    概述:数组定义时,数组长度是预先定义好的,整个程序中固定不变。但实际编程中,往往需要根据实际情况申请空间。
    C语言提供了一些内存管理函数,可以通过需要动态分配内存空间,也可以把不在使用的空间回收。
3.静态分配
    1》在编译或者运行时,按事先规定的大小分配空间,比如int a[10],系统自动分配。
    2》必须事先指定所需空间大小。
    3》分配在栈区或全局变量区,一般以数组形式
    4》按计划分配

                                    int a = 10; //这个就是静态分配(系统自动分配)
4.动态分配
    1》在程序运行中,根据需要大小自由分配,需要程序员自己分配
    2》分配在堆区,一般使用特定函数进行分配
    3》按需分配

	int *p;
	//用malloc申请一个存10个int型元素的数组 
	p = (int *)malloc(sizeof(int)*10); 
	if(p==NULL)
	{
		printf("error\n");
	 }

5.动态分配函数
    1》malloc函数:开辟一片连续的内存空间,需要手动初始化
    语法:指针变量接收 = malloc (需要开辟的空间大小字节数)
            指针变量接收 = malloc (元素类型字节数*元素个数)
    注意指针变量类型需要开辟所需的数据类型保持一致

	  //这个函数是给malloc手动初始化函数 
	 memset(p,0,40);  // memset函数对申请的空间初始化  memset是否可以置其余的值 
	 //memset()  查找这个函数在#include<string.h>这个头文件查找 
	 int i;
	 for(i=0;i<10;i++)
	 {
	 	p[i] = i; 
	 	printf("%d\n",p[i]);
	  } 

  2》free函数
    语法:free(指针变量)

	  free(p);//如果没有释放申请的空间 ,会造成内存泄漏, 内存泄漏是指只申请不释放。 
	  p = NULL;//防止称为野指针 

3》calloc函数:开辟一片连续的内存空间,==自动初始化为0==
        语法:指针变量接收 = calloc(元素个数,元素类型所占的字节数)

#include<stdio.h>

int main()
{
	int *p;
	p = (int *)calloc(20,sizeof(int)*20); //calloc()等价于mallco()和memset()
	if(p == NULL)
	{
		printf("error\n");
	 } 
	 int i;
	 for(i=0;i<20;i++)
	 {
	 	p[i] = i;
	 	printf("%d\n",p[i]);
	 }
	 free(p);
	 p = NULL;
	return 0;
}

   4》recalloc函数:重新分配 (或称修改已分配的)内存空间大小,主要是进行扩展内存空间。
    语法:指针变量接收 = recalloc(已分配存储区指针变量,重新分配空间大小的字节数)

	  p = realloc(p,100);//realloc用来对空间进行扩容,原来数据保留,新增加的空间值是随机的 
	  {
	  	if(p==NULL)
	  	{
	  		printf("error\n");
		  }
	  }
	  
//初始化扩容的数据第一种方法	  
//	  int *pa;
//	  pa = p;
//	  pa = pa+10;
//	  memset(pa,0,60);

//初始化扩容的数据第二种方法
//	memset(p+10,0,60); 

//初始化扩容的数据第三种方法
//	for(i=10;i<25;i++)
//	{
//		p[i] = 0;
//	}

	  for(i=0;i<25;i++)
	 {
//	 	p[i] = i; 
	 	printf("%d\n",p[i]);
	  } 

上面有重新分配后,将扩容的函数进行初始化的是那种方法!!!

4.内存泄漏

        内存泄漏概念:申请的内存,首地址丢了,找不到了,再也没有办法使用了,也没有办法释放,这块内存就泄露了

char  *p;
p = (char *)malloc(100);    //p指向申请的地址

p = "hello world";       //p重新指向了字符串,之前申请的地址将无法找到

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值