指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。
题目场景:
下列代码输出是()
char *a[] = {"BEIJING", "SHENZHEN", "SHANGHAI", "GUANGZHOU"};
char **pa[] = {a+3, a+2, a+1, a};
char ***ppa = pa;
int main(void) {
printf("%s, ", **++ppa);
printf("%s, ", *--*++ppa+3);
printf("%s, ", *ppa[-2]+3);
printf("%s", ppa[-1][-1]+1);
}
答案输出
SHANGHAI, JING, NGZHOU, HENZHEN
原因分析:

- 由于pa 本身为一个常量指针,而且其类型为char ** ,所以pa是一个三级指针,依次执行输出语句,
printf("%s, ", **++ppa);
在C语言中,++前缀递增递减和 *优先级相同,从右到左;后缀递增递减比前缀优先级高,从左到右;
所以在该语句中,程序先执行
++ ppa
ppa自增,指向改变,向后移动一位,偏移量为 char **,指向pa[1]。
*++ ppa
取出pa[1]的内容,pa[1]又指向了a[2] 的地址。
**++ ppa
取出 a[2]的内容,a[2] 又指向字符串 "SHANGHAI",所以输出SHANGHAI
- 运算符优先级:++/-- 优先级大于 + ,且 + 的结合性是从左往右
printf("%s, ", *--*++ppa+3);
由于在C语言中,++/-- 优先级大于 +,由上面可得出
++ ppa
在上一次操作中,函数中已经改变了 ppa 的指向为pa[1],所以在这次操作中,其指向改变,向后继续移动一位,指向pa [2] 。
*++ ppa
取出pa[2]的内容,pa[2]又指向了a[1] 的地址。
--*++ ppa
当对其进行--操作时,由于指向了 a[1]的地址,从 a[1] 向前移动一个 char * 的大小,指向a[0]。
*--*++ ppa
取出 a[0]的内容,a[0] 又指向字符串 "BEIJING",所以输出BEIJING
*--*++ ppa +3
由于其输出BEIJING ,对其+3使得指针向后移动3位,指针指向 J,对其进行输出,得到JING
- ppa[-2]等价于 *(ppa-2)
printf("%s, ", *ppa[-2]+3);
根据上面的可知,ppa 此时指向pa+2,执行ppa[-2],(ppa+2)-2 = ppa,故ppa 指向pa 的首地址,即指向 pa[0] 的地址。
*ppa[-2]
取出 a[3] 的内容,a[3] 又指向字符串 "GUANGZHOU",所以输出GUANGZHOU
*ppa[-2] +3
由于其输出 GUANGZHOU,对其+3使得指针向后移动3位,指针指向 N,对其进行输出,得到 NGZHOU.。
- ppa[-1][-1]等价于*(*(ppa-1)-1),ppa[-1] 等价于 *(ppa-1)
printf("%s", ppa[-1][-1]+1);
经过前面的操作, ppa 此时指向pa[2]。
当执行 ppa[-1],相当于*(ppa -1)。所以其将会指向数组 pa[1] 。取出内容 pa[1] ,pa[1]又指向 a[2]
ppa[-1][-1] 等价于 *(ppa[-1]-1)
在向前移动一次,移动后指向 a[1],取出内容a[1]的内容,a[1]又指向字符串SHENZHEN
ppa[-1][-1]+1
由于其输出 SHENZHEN,对其+1使得指针向后移动1位,指针指向 H,对其进行输出,得到 HENZHEN。