最近复习了一下C语言中的指针数组、数组指针这些比较让人困惑的概念,有了一些新的认识。
一、变量定义中的优先级
在定义变量时,需要用到一些运算符,比如[]、*、()。这些运算符有一定优先级,我们可以根据其优先级来对我们定义的变量进行理解。具体的方法就是:加括号。下面举几个例子:
(1)二维数组
定义:int a[3][4];
理解:[]运算符遵循从左到右的顺序,因此上面的表达式可以理解为:int (a[3])[4]; 括号()里面表明a是一个长度为3的数组,括号外面表明这个数组的元素是int[4]类型的(数组的元素也是数组)。
(2)指针数组
定义:int *p[3];
理解:[]的优先级高于*,因此上面的表达式可以理解为:int *(p[3]); 括号里面表明p是一个长度为3的数组,括号外面表明这个数组的元素是int*类型的(数组的元素是指针)。
(3)指针的指针
定义:int **pp;
理解:*运算符遵循从右到左的顺序,因此上面的表达式可以理解为:int *(*pp); 括号里面表明pp是一个指针,括号外面表明这个指针指向的元素是int*类型的(指针指向指针)。
(4)二维数组的指针
定义:int (*pa)[4];
理解:上面的表达式已经带括号()了,括号里面表明pa是一个指针,括号外面表明这个指针指向的元素是int[4]类型的(指针指向数组)。
二、数组中的地址、元素
一个数组a,无论是一维数组、二维数组还是指针数组,有以下几点共同的属性:
- a放在表达式中,表示的是数组首元素的地址;对地址进行加减运算得到的还是地址,那么a+i就表示的是第i个元素的地址;
- a[i]:表示a的第i个元素。
- &a[i]:由于[]的优先级高于&,该表达式可以改写为&(a[i]),也就是第i个元素的地址。这正等价于a+i。
三、二维数组的索引
有了前两节的知识储备,我们再来看二维数组。设有一个二维数组int a[3][4];
- 根据第一节,a是一个数组,a的元素是int[4]型的数组。
- a是这个数组的首元素(即第0个int[4]数组,也就是第0行)的地址,a+i是第i行的地址。
- a[i]是a的第i个元素,也就是第i个int[4]数组(第i行)。
- 既然a[i]是数组,那么a[i]本身又是这个数组(第i行)的首地址,即第i行第0列的地址,而a[i]+j就是第i行第j列的地址。
- &a[i]等价于a+i,即第i行的地址。
运用以上的结论,我们举几个例子:
- &a[1]+1是第2行的首地址。
- a[1]+1是第1行第1列的地址。