在上一张已经练习了三道习题,小试牛刀了,那么在本章在来几题,练练手。(习题三是压轴难题)
习题一
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&aa + 1);int* ptr2 = (int*)(*(aa + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
这里借助画图也可以更好的理解。
&aa是整个数组的地址,那么加一就是跳过整个数组,指向数组末尾之后的位置。强制转换为int*后,ptr1指向数组末尾后的地址。
看图。

欧克,那么ptr1 - 1回退一个int的位置,指向数组最后一个元素10。那么ptr1-1就指向10
所以第一个输出10.
第二个:1. aa在表达式中退化为int (*)[5](指向第一行的指针)。
2. aa + 1指向第二行的首地址(即元素6的地址)。
3. *(aa + 1)解引用得到第二行的数组,退化为int*指向6。
4. ptr2 - 1回退一个int的位置,指向第一行的最后一个元素5,故*(ptr2 - 1)为5。
所以本题的答案为 10,5
习题二
#include <stdio.h>
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}
数组名 a 在表达式中退化为 char** 类型(指向第一个元素 a[0] 的指针)。
char** pa = a; // pa 指向 a[0]
pa 的类型是 char**,指向 a 的第一个元素 a[0](即字符串 "work" 的地址)。
pa++; // pa 移动到 a[1]
-
pa是char**类型,指向char*元素。 -
执行后,
pa指向数组的第二个元素a[1](即字符串"at"的地址)。 -
printf("%s\n", *pa); // 输出 a[1] 指向的字符串 -
*pa解引用pa,得到a[1]的值(即字符串"at"的首地址)。 -
用
%s格式输出时,会打印从该地址开始的字符串"at"。 -
答案为 at
习题三
注意:此题为压轴题,请认真分析,一定一定要画图。
#include <stdio.h>int main()
{char* c[] = { "ENTER","NEW","POINT","FIRST" };char** cp[] = { c + 3,c + 2,c + 1,c };char*** cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *-- * ++cpp + 3);printf("%s\n", *cpp[-2] + 3);printf("%s\n", cpp[-1][-1] + 1);return 0;
}
答案:
POINT
ER
ST
EW
做本题首先要画图,上图。

这是在运算前的必要流程,由此图我们可以相对容易理解。
那么接下来 SHOW TIME
一:
printf("%s\n",**++cpp);
这步先找突破口,cpp,
步骤如下:
++cpp:将cpp增加1,使其指向cp[1]。*cpp:解引用cpp,得到cp[1],即c + 2。**cpp:解引用*cpp,得到*(c + 2),即"POINT"。
所以结果输出 POINT
二:
printf("%s\n", *-- * ++cpp + 3);
做这道题之前可以将本题简化一下,简化后为 * --*++cpp +3
因此,第二个 printf 输出 "ER"。
++cpp:将cpp增加1,使其指向cp[2]。(PS:在上一步已经将进行一次++cpp,所以这里初始状态就是cpp[1])*cpp:解引用cpp,得到cp[2],即c + 1。--*cpp:将*cpp减少1,使其指向c,即"ENTER"。*--*cpp + 3:解引用--*cpp,得到"ENTER",然后加上3,指向"ENTER"的第4个字符,即"ER"。
三:
printf("%s\n", *cpp[-2] + 3);
这里也可以进行一步简化,cpp[-2]:相当于 *(cpp-2):
cpp[-2]:由于cpp当前指向cp[2],所以cpp[-2]指向cp[0]。*cpp[-2]:解引用cpp[-2],得到cp[0],即c + 3。*cpp[-2] + 3:解引用*cpp[-2],得到"FIRST",然后加上3,指向"FIRST"的第4个字符,即"ST"。
因此,第三个 printf 输出 "ST"。

printf("%s\n", cpp[-1][-1] + 1);
cpp[-1]:由于cpp当前指向cp[2],所以cpp[-1]指向cp[1]。cpp[-1][-1]:解引用cpp[-1],得到cp[1],即c + 2,然后解引用-1,得到*(c + 1),即"NEW"。cpp[-1][-1] + 1:解引用cpp[-1][-1],得到"NEW",然后加上1,指向"NEW"的第2个字符,即"EW"。
因此,第四个 printf 输出 "EW"。

欧克 指针运算的习题就到这里了,大家可以在独立运算一下,更好的理解。
