上一期内容,大多数的解题思路写在代码中,没有写在正文中,这就导致系统判断文章质量不高,没有什么数据,这一期将思路写在正文中。
注意:运行环境是x86
1.题目1
思路:
&a是取到了整个数组的地址,值为首元素的地址,+1的步长是整个数组,所以+1之后指针指向了下图所示的位置,此时它的类型是Int(*)[5],是一个数组指针。
此时强转指针的类型为int*,其实就是改变了指针移动的步长,跳过一个整型;查看输出内容,a+1是第二个元素的地址再解引用是第二个元素2,指针ptr-1,刚刚已经说明步长已经发生改变,所以这里指针向前挪动一个元素,答案是5;
答案:2 5
2.题目2
思路:
首先定义了一个结构体指针p,已知结构体变量是20字节。
①输出结构体指针+1,这里步长是一个结构体,一个结构体是20字节,所以要加20,转换成16进制就是:0x100014;
②将指针转成整型,再加一,其实直接就是数值+1,0x100001;
③将指针转换成整型指针,加一,就是加四个字节,0x100004
答案:0x100014;0x100001;0x100004
3.题目3
思路:
第一个输出结果是4,这是因为先取出整个数组的地址再+1,指针在4的后面,强转成int*了,ptr[-1]等价于*(ptr - 1) ,就是元素4;
第二个输出结果是2000000,首先将整个数组的地址强转成整型再+1,这里的整型是直接+1,举一个例子如下图,如果是整型+1直接跳过一个整型,但是这里是转换成整型+1,就跟数字加法一样直接加一。
这里的每一个元素都是四个字节存储,+1之后只是跳过了一个字节,记住vs是小端存储,数字的低位在低地址,具体的内存图如下。 int*解引用之后,得到了02 00 00 00,输出就是20 00 000
4.题目4
答案:1
解析:易错题,注意数组大括号的内部是小括号,这里考察逗号表达式,(0,1)这里的结果是1;(2,3)结果是3,以此类推...所以数组存放了三个元素:1,3,5;p指针指向第一行,p[0]是*(p+0)所以即求第一行第一个元素,即1;
5.题目5
分析:
a是首元素地址,也就是一维数组的地址,类型是int(*)[5];p的类型是int(*)[4],这里显然类型不匹配,但是依旧强行赋值;此时p+1会跳过4个整型;a[4][2]很容易找到,p[4][2]等价于*(*(p+4)+2)首先,p先加4,每加1跳过四个字节,解引用之后就是int*了,每次跳过一个字节,跳两个字节,最后取地址。下图蓝色的部分就是p[4][2],红色的部分是a[4][2]。
使用整型打印那就是小地址-大地址 = -4;如果按照指针打印就看-4如何在内存中存储了;
-4的原码反码补码如下,按照%d的格式进行打印的是原码,按照%p格式打印的是地址,而内存中存储的就是地址,也就是补码,转换成16进制输出那就是:FFFFFFFC
答案;FFFFFFFC,-4
6.题目6
答案:10,5
分析:第一个取二维数组的地址+1,跳过整个数组,强转int*输出再-1,即输出最后一个元素10;
第二个aa是首元素的地址,即第一行的地址,即一维数组的地址,+1之后就是第二行的地址,再解引用那就是第二行首元素的地址,即6的地址,再-1,最后输出就是5;
7.题目7
分析:
内存示意图如下,char* *pa,可以这么理解:指针*pa指向的是一个char*的元素,所以pa++的时候会跳过一个char*的,直接跳到了at的地址,所以输出at。
答案:at
8.题目8(最难)
分析:画出三种指针的内存图;
①cpp自增1,指向c+2的地址,解引用拿到c+2(POINT的地址),,再解引用得到P的地址,打印得到:POINT。
②cpp自增1,从c+2到c+1,再解引用得到NEW的地址,再--得到ENTER的地址,再解引用得到E的地址,再+3得到E的地址,打印输出ER。
③cpp[-2]等价于*(cpp-2),cpp从c+1的位置回到了c+3的位置,解引用得到c+3,即FIRST的地址,再解引用得到F的地址,最后+3得到S的地址,输出ST。
④cpp[-1][-1]等价于*(*(cpp - 1) -1),cpp在c+1的位置-1之后在c+2的位置,解引用得到c+2,即POINT的地址,再-1得到NEW的地址,最后解引用得到N的地址,最后+1得到E的地址,输出EW。