二级指针原理及结构体数组及结构体指针数组的应用

指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。

如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。

假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

将这种关系转换为C语言代码:

 
  1. int a =100;
  2. int *p1 = &a;
  3. int **p2 = &p1;

指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级指针,指向一级指针 p1,定义时有两个*

如果我们希望再定义一个三级指针 p3,让它指向 p2,那么可以这样写:

 
  1. int ***p3 = &p2;

四级指针也是类似的道理:

 
  1. int ****p4 = &p3;

实际开发中会经常使用一级指针和二级指针,几乎用不到高级指针。

想要获取指针指向的数据时,一级指针加一个*,二级指针加两个*,三级指针加三个*,以此类推,请看代码:

 
  1. #include <stdio.h>
  2.  
  3. int main(){
  4. int a =100;
  5. int *p1 = &a;
  6. int **p2 = &p1;
  7. int ***p3 = &p2;
  8.  
  9. printf("%d, %d, %d, %d\n", a, *p1, **p2, ***p3);
  10. printf("&p2 = %#X, p3 = %#X\n", &p2, p3);
  11. printf("&p1 = %#X, p2 = %#X, *p3 = %#X\n", &p1, p2, *p3);
  12. printf(" &a = %#X, p1 = %#X, *p2 = %#X, **p3 = %#X\n", &a, p1, *p2, **p3);
  13. return 0;
  14. }

运行结果:

100, 100, 100, 100
&p2 = 0X28FF3C, p3 = 0X28FF3C
&p1 = 0X28FF40, p2 = 0X28FF40, *p3 = 0X28FF40
 &a = 0X28FF44, p1 = 0X28FF44, *p2 = 0X28FF44, **p3 = 0X28FF44

以三级指针 p3 为例来分析上面的代码。***p3等价于*(*(*p3))。*p3 得到的是 p2 的值,也即 p1 的地址;*(*p3) 得到的是 p1 的值,也即 a 的地址;经过三次“取值”操作后,*(*(*p3)) 得到的才是 a 的值。

具体实际应用代码

#include"stdio.h"
  2 
  3 struct student
  4 {
  5         int num;
  6         char name[20];
  7         char sex;
  8         float score;
  9 };
 10 
 11 void input_initial(struct student stu[])
 12 {
 13         int i=0;
 14         for(i=0;i<3;i++)
 15         {
 16                 printf("please input a man information\n");
 17                 scanf("%d %s %c %f",&stu[i].num,\
 18                                         stu[i].name,\
 19                                         &stu[i].sex,\
 20                                         &stu[i].score);
 21         }
 22 }
 23 
 24 void output_information(struct student *pstu[])
 25 {
 26         int i=0;
 27         for(i=0;i<3;i++)
 28         {
 29                 printf("%d %s %c %f\n",pstu[i]->num,\
 30                                         pstu[i]->name,\
 31                                         pstu[i]->sex,\
 32                                         pstu[i]->score);
 33         }
 34 }
 35 void swap(struct student **a,struct student **b)
 36 {
 37         struct student *c;
 38          c=*a;
 39         *a=*b;
 40         *b=c;
 41 }
 42 void mopao_sort(struct student *pstu[],int len)
 43 {
 44         int i=0;
 45         int j=0;
 46         struct student *ptemp;
 47         for(i=0;i<len-1;i++)
 48         {
 49                 for(j=1;j<len;j++)
 50                 {
 51                         if(pstu[j-1]->num>pstu[j]->num)
 52                         {
 53                                 swap(&pstu[j-1],&pstu[j]);
 54                                 /*ptemp=pstu[j-1];
 55                                 pstu[j-1]=pstu[j];
 56                                 pstu[j]=ptemp;*/
 57                         }
 58                 }
 59         }
 60 }
 61 void main()
 62 {
 63         struct student stu[5];
 64         struct student *pstu[5]={stu,stu+1,stu+2,stu+3,stu+4};
 65         input_initial(stu);
 66         mopao_sort(pstu,3);
 67         output_information(pstu);
 68 
 69 }

代码中的void swap(struct student **a,struct student **b)函数中

用到了二级指针,为什么要用到二级指针呢,因为我们在swap函数中要实现stu地址的交换,

**a=&pstu

*a相当于访问了pstu地址的值,即为stu的地址

**a相当于访问了stu的值

故函数体内部要用

c=*a;

*a=*b

*b=c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值