----在学习指针这一块,有三个地方最让人头痛,因为当时你搞懂了,但是一段时间没用,等到你再次去用的时候,你会发现自己又感觉一脸懵逼的状态,脑袋里面只依稀记得有这么一个概念,但是具体用法怎么也想不起来了,这个想必大多数人和我一样,有过这样的经历。而这三个头痛的地方分别是:


         1、const修饰指针的用法,主要是const它放的位置,一改变位置,它表示的意思就不一样了:             

                  第一种:const int *p;

                  第二种:int const *p;

                  第三种:int * const p;

                  第四种:const int * const p;

当你第一眼看到这些,你会用它吗?我自己的话,说实话很长时间,没用的话,确实会被搞晕,这里小结一下(具体可以看我之前写的一遍有关const的用法,理解了下面的两句话,就不要向以前那样去死记硬背了,自己可以写代码测试一下,你就全明白了,这是最好的方法,个人建议):

            a、const在*前面,就表示cosnt作用于p所指向的是一个常量

           b、const在*的后面,表示p本身是一个常量,但是p指向的不一定是常量


         2、数组指针和指针数组的区别(今天的主题)。


        3、函数指针和指针函数的区别(下一篇文章会进行详细讲解的)。



一、数组指针与指针数组的区别:


1、从字面意思去理解他两的区别:



       (1)指针数组的实质是一个数组,这个数组中存储的内容全部是指针变量。换句通俗的话来讲,指针数组就是指针的数组,核心是一个数组,什么样的数组呢?装着指针的数组。

      (2)数组指针的实质是一个指针,这个指针指向的是一个数组。也可以换句通俗的话语来理解,数组指针就是数组的指针,核心是一个指针,什么样的指针呢?指向数组的指针。


2、分析数组指针和指针数组的表达式:



     ​   (1)先看这个三个表达式:

                int *p[5]; 

                int (*p)[5];

                int *(p[5]);


       (2)我们先来看一下这个规律)不要下次还是死记硬背关于数组指针和指针数组的区别,关键还是理解为主):


            我们在定义一个符号时,关键在于:首先要搞清楚你定义的符号是谁:

          第一步:找核心(也就是谁是这个表达式里面的主体(变量))。

              第二步:找结合:

                           看谁跟核心最近、谁跟核心结合。如果核心和*结合,表示核心是指针;如果核心和[]结合,表示核心是数组;如果核心和()结合,表示核心是函数。

              第三步:以后继续向外扩展




      ​ (3)用上面的规律来分析这3个符号:



   ​          第一个,int *p[5]; 核心是p,p是一个数组,数组有5个元素,数组中的元素都是指针,指针指向的元素类型是int类型的;整个符号是一个指针数组。

             第二个,int (*p)[5];

核心是p,p是一个指针,指针指向一个数组,数组有5个元素,数组中存的元素是int类型; 总结一下整个符号的意义就是数组指针。

            第三个,int *(p[5]); 解析方法和结论和第一个相同,()在这里是可有可无的。



             注意:这里要知道[]符号比*符号的优先级高,()的优先级最高


3、实例代码来加深理解:


 ​     1、数组指针:

1#include <stdio.h>
2 int main()
3 {
4
5//定义一个数组
6int a[5]={1,2,3,4,5};
7//定义一个数组指针
8int (*p)[5] ;
9//把数组a的地址赋给p,则p为数组a的地址
10p=&a;
11
12printf("0x%x\n",a);//输出数组名,一般用数组的首元素地址来标识一个数组,则输出数组首元素地址
13printf("0x%x\n",p);//根据上面,p为数组a的地址,输出数组a的地址
14printf("%p\n",*p);//*p表示数组a本身,一般用数组的首元素地址来标识一个数组
15
16printf("0x%x\n",&a[0]);//a[0]的地址
17printf("0x%x\n",&a[1]);//a[1]的地址
18printf("0x%x\n",p[0]);//数组首元素的地址
19printf("%d\n",**p);//*p为数组a本身,即为数组a首元素地址,则*(*p)为值,当*p为数组首元素地址时,**p表示首元素的值1
20
21printf("%d\n",*p[0]);//根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
22printf("%d\n",*p[2]);//为一个绝对值很大的数值
23
24
25return 0;
26
27}

输出结果:


c专题之指针---数组指针与指针数组的区别_指针数组


2、指针数组:




1#include <stdio.h>
2int main()
3 {
4 int a=1;
5 int b=2;
6 int *p[2];
7 p[0]=&a;
8 p[1]=&b;
9
10printf("0x%x\n",p[0]);
11printf("0x%x\n",&a);
12printf("0x%x\n",p[1]);
13printf("0x%x\n",&b);
14printf("%d\n",*p[0]);
15printf("%d\n",*p[1]);
16
17return 0;
18
19}

输出结果:

c专题之指针---数组指针与指针数组的区别_数组_02


三、总结:


      ​   不知大家在看完后,有没有完全理解了他两的区别了,以后不要再去记他们的区别了,理解最重要。


---欢迎关注公众号,可以查看往期的文章,可以得到三本经典的c语言进阶电子书:

c专题之指针---数组指针与指针数组的区别_数组_03

Linux爱好者(对文章中写有不对的地方,可以批评指出,虚心向您学习,大家一起进步。可以进群交流有关Linux的技术等话题,群里只能讨论技术,发广告,立刻飞机):