指针数组和数组指针

指针数组和数组指针

        大家看到这两个词,是不是有点头大呢?

        别说你们。我看着都有点头大,虽然知道什么时数组,什么是指针,但是他们结合起来是个什么玩意呢?

        相比大家对数组和指针应该耳熟能详了吧,那么有这两个基础了,咱们再来看今天我们要讨论的指针数组和数组指针。

指针数组

        以前我们在学习数组的时候,肯定听说过整型数组,字符数组,浮点型数组之类的,既然数组其中可以放字符、整数、浮点数,那么可不可以放其他的东西呢?答案当然是可以的,比如放结构体,就是结构体数组,那么如果行的是指针呢?是不是就成了我们今天主要说的指针数组了呢?答案是肯定的。

        那么我们的指针数组离如何去定义呢?我们都知道普通的整型数组,字符数组,浮点型数组是这样的

  int Arr[10];
  char Arr[10];
  double Arr[10];
  struct Student FirstClass[20];

        他们内部分别存的是整型、字符型、浮点型的数组,他们的类型就是其相对应的类型,那么我们要存一个整型指针呢?是不是数组的类型就是整型指针类型的呢?所以我们的指针数组是这样定义的:

  int *Arr[10];   //(一级)整型指针数组
  double *Arr[10];//(一级)字符指针数组
  float **Arr[10];//二级单精度指针数组

        那么问题来了,指针数组到底时指针还是数组呢

        答案是数组,它和我们一般见到的数组并没有的区别,只是它的内部存储的是一个指针而已。

数组指针

        以前我们在学习指针的时候,是不是有整型指针,字符指针,还有浮点数指针呢?他们代表的意思都是指向该类型数据地址最小的字节,再根据其内部数据类型的大小就可以得到该数据。那么我们定义一个结构体变量,那么他有地址吗?答案是肯定的,所以指向结构体的指针就叫做结构体指针。那么我们的数组有地址吗?答案也是有,那么指向数组的指针就叫做数组指针。

        那么如何定义呢?整型指针、字符指针、浮点数指针相信大家都会吧,我们举几个例子:

  int *pint;
  float *pfloat;
  char *pchar;
  struct Student *Stu;

        他们都是指向其对应类型的指针,那么我们的数组指针呢?数组指针定义比较特殊,我们就直接开门见山:

  int (*p)[10];   //指向大小为10的整型数组指针
  float (*p)[20]; //指向大小为20的浮点型数组指针
  int (*p[10])[20];   //那么这个呢?这个我们接下来会说

        那么问题又来了,数组指针是数组还是指针呢?

        答案是指针,它是一个指向数组的指针。

        那么这两个这么像,而且又这么绕,我们之后见到该辨别呢?下面我们就说以下他们两个的辨别。

如何辨别指针数组和数组指针

  int *p[10];
  int (*p)[10];
  int (*p[10])[20];

        大家还能分清楚这前两个吗?很多人会说能,但是第三个呢,到底是指针数组还是数组指针呢?

        这下就蒙圈了吧:/手动得意 我们来看一看,我们可以把他们分为四部分来看

                int         *         p         [10]

        第一部分是类型,第二部分是星号,第三部分是变量名,第四部分数数组的大小

        那么 我们的变量名 p 是优先和谁结合呢?是 * 号 , 还是我们的 [ ] 中括号呢?

        根据我们的优先级表可以得出 [ ] 中括号的优先级要高于 * 星号的 ,所以我们的变量名 p 是先和 [ ] 结合形成数组,所以他就是一个数组,然后在和 int * 结合 ,这就是我们的指针数组。

        那么我们如果给星号 * 和 p 变量名带上圆括号呢?那么我们的 p 就先会和 * 进行结合变成一个指针,所以他就是一个指针,再和int [10] 结合变成一个指向大小为10的整型数组的指针。

        所以归根结底,看的是变量名与哪一个先结合,先和 [ ] 结合,它就是数组;先和 * 结合 他就是一个指针。

        注:数组的类型是由其基本类型加上其大小组成的,两个是强相关的。比如 int Arr[10] ,那么这个数组的类型其实就是 int [ 10 ],读者这里要注意。

        那么大家知道,对指针进行++操作,就是给它加上其类型的大小。那么对我们的数组指针而言呢?

  #include <stdio.h>
  int main()
  {
      int arr[10] = { 0 };
      printf("arr = %p\n", arr);      //arr 为数组首元素的地址     指向其内部元素的指针
      printf("&arr= %p\n", &arr);     //&arr 为整个数组的地址      指向整个数组的指针
      
      printf("arr+1 = %p\n", arr+1);  
      printf("&arr+1= %p\n", &arr+1);
      return 0;
  }

        所以对我们数组指针而言,对它++就是相当于跳过了整个数组。

二维数组传参

        相信我们对一维数组传参已经很清楚了;那么二维数组是怎样传参的呢?我们来看一段代码:

  int Print1(int Arr[10][20], int row , int col){}
  int Print2(int Arr[][20], int row , int col){}
  int Print3(int (*Arr)[20], int row , int col){}
  ​
  int main(){
      int Arr[10][20] = { 0 };
      Print1(Arr,10,20);
      Print2(Arr,10,20);
      Print3(Arr,10,20);
      return 0;
  }

        请问,以上三种传参方式,那个对,那个不对呢?

        其实以上三种传参方式都是对的,而且都是一样的,但是为什么呢?

        大家都知道数组在传参时,或发生降维,降维成指针。所以第一种传参会降维,降维成指向其内部元素类型的指针,即就是指向一个大小为20的整型一维数组的指针,降维后其实就是 int (*Arr)[20],是不是和第三个一模一样呢?

        我们知道数组在传参时第一维可以省略,那么为什么可以省略呢?我们可以看一下以下代码:

  void Fun1(int Arr[100], int line){}
  void Fun2(int *Arr, int line){}
  int main(){
      int Arr[10];
      Fun(Arr,10);
  }

        大家在编译是会发现没有任何问题,是不是很奇怪?就是因为数组在传参时会降维,降维成指向其内部元素类型的指针,所以形参哪里填多少都没有关系,但是在传参时一定要把它的个各维的大小传进去,才能正确的访问其内部元素。

        所以我们在进行数组传参时,我们可以有两种方式可以使用,可以根据个人喜好来进行选择

总结

        今天我们主要讨论了数组指针和指针数组,今天主要是对其基本的概念进行讨论,到底如何去用,在什么场景下使用,我们以后再做以讨论。

 

        由于本人才疏学浅,若有疏忽还望不吝赐教。

        @YeLing0119

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值