6
题干
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; }
答案
10,5
解析
&aa + 1
取出二维数组的地址,再+1,跳过了这个二维数组,
&aa + 1是数组指针,要进行强制类型转换,转换成int*类型
*(aa + 1)
aa是数组名,表示的是二维数组的首元素,即第一行元素
(aa + 1)跳过了一行,指向的是第二行元素
解引用之后, *(aa + 1) == aa[1],也就是第二行元素的数组名,表示的是第二行首元素6的地址
*(ptr1 - 1)
ptr1是整型指针,减一之后,指向10,
解引用之后输出的结果是10
*(ptr2 - 1)
ptr2是整型指针,减一,指向5这个元素
多说一句:
ptr2在转换类型之前,就是int*类型,之后再进行类型转换可能只是为了形式美观
7
题干
#include<stdio.h> int main() { char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; printf("%s\n", *pa); return 0; }
答案
at
解析
温习旧识
字符指针
char *p = “abcdef”
该指针存储的是,该常量字符串的首元素a
a[]
a[],是字符指针数组,每个元素存储的都是字符串的首元素的地址,
如图:
a是数组名,存储的是首元素的地址,
即‘w’
pa
pa是二级指针变量,存储的是a数组首元素的地址
pa++,跳过的是pa指向元素的类型的大小,而它指向的元素类型是char*,指向的就是a数组中的第二个元素
,也就是at中a的地址
那么以字符串的形式打印*(pa),结果就是at
8
题干
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
解析
很多朋友看到这道题可能想放弃,不要放弃,我们一步一步来分析
c[]
字符指针数组,四个元素,存储的分别是E、N、P、F的地址,
如图:
cp[]
二级字符指针数组,c是数组的数组名,即首元素的地址,
自己进行一一对应
cpp
三级指针,存储的是cp的地址,也就是cp首元素的地址
如图:
**++cpp
cpp先自增,如图
再解引用两次,第一次解引用获得c+2,第二次解引用获得字符P的地址
再以字符串的形式打印出point
*-- * ++cpp + 3
先计算++cpp
注意:此时cpp的生命周期没有结束,还在代码块之内
解引用获得c+1
再自减,变成c
此时再进行解引用,得到字符‘E’的地址,
最后+3(向后移动三位),此时指向的就是ENTER中的第二个E
最终输出结果就是ER
*cpp[-2] + 3
cpp[-2] == *(cpp+(-2))
*cpp[-2] == **(cpp+(-2))
*cpp[-2] + 3 == **(cpp - 2) + 3
(cpp - 2)指向的是c+3
两次解引用之后,字符F的地址
+3,向后移动三位,是字符S的地址
打印结果是:
ST
cpp[-1][-1] + 1
cpp[-1][-1] == *(*(cpp-1)-1)
cpp-1,指向的是c+2
如图
c+2,再减一,变成c+1
之后解引用获得字符N的地址,
加1,指向的是字符E,
最终打印的结果就是EW
结语
这8道题到这里就讲解结束了,怎么样,希望你有所收获
这类题作为笔试题,很强调自己对于画图能力的要求,这也是很重要的
我们下篇文章再见~