在上一张已经练习了三道习题,小试牛刀了,那么在本章在来几题,练练手。(习题三是压轴难题)
习题一
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"
。
欧克 指针运算的习题就到这里了,大家可以在独立运算一下,更好的理解。