【C语言零基础入门篇 - 12】:指针进阶

指针进阶


内存四区

在系统为程序开辟内存时,将内存区域划分为4块,分别为:

(1)栈区
(2)堆区
(3)全局静态常量区(全局区)
(4)代码区

栈区:存放函数的形参、局部变量等。由编译器自动分配和释放,当函数执行完毕时自动释放。
堆区:用于动态内存的申请与释放,一般由程序员手动分配和释放,若程序员不释放,则程序结束时由操作系统回收。
全局静态常量区(全局区):用于动态内存的申请与释放,一般由程序员手动分配和释放,若程序员不释放,则程序结束时由操作系统回收。
在这里插入图片描述
代码区:存放可执行的代码,一般为CPU 执行的机器指令。(由编译器翻译后的指令放在代码区)

结构体指针变量的使用

结构体指针变量:是一个保存结构体变量地址的指针变量,我们对这个指针变量进行解引用,就可访问到这个结构体变量的数据以及更改数据。

结构体指针变量的定义格式:指针指向的类型 * 指针名 = NULL;
在这里插入图片描述

结构体指针

通过结构体指针引用结构体变量及其结构体成员:

结构体指针引用符:‘->’

结构体指针引用成员的基本格式:结构体指针名->结构体成员名

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结构体指针数组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 方式一:通过for循环输出成员的名字
    在这里插入图片描述
  • 方式二:通过p = p->next,来获取成员名字并输出
    在这里插入图片描述

动态内存分配

什么是动态内存分配:
指用户可以根据自己的需要,向系统申请所需大小的内存空间;由于没有声明部分来定义它们是为变量的地址还是为数组的地址,所以只能通过指针来引用它们。

要使用动态内存开辟,需要包含stdlib.h头文件

怎样建立内存的动态分配
①malloc函数:malloc(int size);
用于分配一个大小为size的内存区域。
例如:char *p=(char *)malloc(100)

②calloc函数:calloc(unsigned n,int size);
用于分配n个大小为size的连续内存区域,可以为一维数组开辟动态内存空间。
例如:int *p=(int *)calloc(10,sizeof(int));

③realloc函数:realloc(void * p,unsigned int size);
用于改变已经通过malloc函数或calloc函数开辟的内存空间的大小。
例如:realloc(p,sizeof(int)*6);

④free函数:void free(void * p);
用于释放指针变量所指向的动态内存空间。
例如:free( p );

注意:动态内存需要手动申请,在对堆区申请,申请完后需要自己释放。

  • 例1:malloc(申请的内存大小) ;单位:字节 ;返回的申请的内存的首地址,默认返回void*类型
  • malloc不会初始化内存数据
    在这里插入图片描述
  • 例2:calloc(多少个元素, 每个元素大小),会初始化内存
    在这里插入图片描述
  • 例3:realloc(首地址, 修改之后的大小)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

扩容

扩容方法:
1、先申请更大的内存空间,拿一个临时指针变量进行管理把原来的数据拷贝到新的大内存中来
2、释放p所指向的旧的内存
3、free(内存的首地址)
4、p指向新的内存

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	int *p = (int*)malloc(25 * sizeof(int));
	//需要对内存做初始化 memset:逐字节初始化 需要引入string.h
	//memset(从哪个地方开始复制,值,复制多少字节)
	memset(p, 0, 25 * sizeof(int));
	for (int j = 0; j < 25; j++)
	{
		p[j] = j + 1;
	}

	//1、先申请更大的内存空间,拿一个临时指针变量进行管理
	int *temp = (int*)malloc(50 * sizeof(int));
	//2、把原来的数据拷贝到新的大内存中来
	for (int j = 0; j < 25; j++)
	{
		temp[j] = p[j];
	}
	//3、释放p所指向的旧的内存
	free(p); //不会把p指针变量释放
	//4、p指向新的内存
	p = temp;
	for (int j = 25; j < 50; j++)
	{
		p[j] = j + 1;
	}
	for (int j = 0; j < 50; j++)
	{
		if (j % 5 == 0 && j != 0)
		{
			printf("\n");
		}
		printf("%d\t", p[j]);
	}
	printf("\n");

	return 0;
}

在这里插入图片描述

多重指针

1、什么是多重指针
指针变量也是有其对应地址的,那么既然有地址,就可以用另一个指针变量指向它的地址,也就是指向指针的指针,简称多重指针。

2、多重指针的定义
定义双重指针(二级指针)基本格式:数据类型 **指针变量名;
定义三重指针(三级指针)基本格式:数据类型 ***指针变量名;
依次类推:四级指针、五级指针……

3、多重指针的使用
如有以下定义:
int a = 10,*p,**q,***r; //定义整型变量a、指针p、双重指针q、三重指针r

则可以有以下赋值语句:
p=&a; //使一级指针p指向变量a的地址
q=&p; //使双重指针q指向一级指针p的地址
r=&q; //使三重指针r指向双重指针q的地址
*p=20; //使用一级指针p给变量a赋值
**q=30; //使用二级指针q给变量a赋值
***r=40; //使用三级指针r给变量a赋值

在这里插入图片描述

双重指针作为函数参数

一般来说函数的形参无法改变实参,除非形参是指针类型的。那么如果实参是一个指针,想要在一个函数中改变一个指针的指向应该怎么做?

例如:若定义了以下函数fun,如果p2是该函数的形参,要求通过p2把动态分配存储单元的地址通过函数参数传回主调函数,则形参p2应当怎样正确定义。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//申请动态内存
void fun(int**p2) //二级指针变量可以接收一级指针变量的地址
{
	//p2=&buff buff相当于*p2
	int *p = (int*)malloc(10 * sizeof(int));
	(*p2) = p;
}
int main()
{
	int *buff = NULL; //buff指向申请的动态内存
	fun(&buff);
	return 0;
}

双重指针可用于在函数中改变一级指针的指向。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

街 三 仔

你的鼓励是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值