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、数组指针:
#include <stdio.h>
int main()
{
//定义一个数组
int a[5]={1,2,3,4,5};
//定义一个数组指针
int (*p)[5] ;
//把数组a的地址赋给p,则p为数组a的地址
p=&a;
printf("0x%x\n",a);//输出数组名,一般用数组的首元素地址来标识一个数组,则输出数组首元素地址
printf("0x%x\n",p);//根据上面,p为数组a的地址,输出数组a的地址
printf("%p\n",*p);//*p表示数组a本身,一般用数组的首元素地址来标识一个数组
printf("0x%x\n",&a[0]);//a[0]的地址
printf("0x%x\n",&a[1]);//a[1]的地址
printf("0x%x\n",p[0]);//数组首元素的地址
printf("%d\n",**p);//*p为数组a本身,即为数组a首元素地址,则*(*p)为值,当*p为数组首元素地址时,**p表示首元素的值1
printf("%d\n",*p[0]);//根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
printf("%d\n",*p[2]);//为一个绝对值很大的数值
return 0;
}
输出结果:
2、指针数组:
#include <stdio.h>
int main()
{
int a=1;
int b=2;
int *p[2];
p[0]=&a;
p[1]=&b;
printf("0x%x\n",p[0]);
printf("0x%x\n",&a);
printf("0x%x\n",p[1]);
printf("0x%x\n",&b);
printf("%d\n",*p[0]);
printf("%d\n",*p[1]);
return 0;
}
输出结果:
三、总结:
不知大家在看完后,有没有完全理解了他两的区别了,以后不要再去记他们的区别了,理解最重要。