第一问:int *ptr1 = (int *)(&a + 1),
&a代表拿出了整个数组的地址,然后+1,此时指针会跳过整个数组,现在的类型是int * [4],它将其强转为了int *,然后问ptr1 [-1]是多少,ptr1 [-1]就是*(ptr+(-1)),就等与*(ptr-1),此时指针应该往回走1个单位,它是int*,所以往回走四个字节,刚好指向了4,所以结果为4。
vs是小端存储,所以从左往右存储数组的时候,是如图所示的存储方式。
第二问如图所示:int *ptr2 = (int *)((int)a + 1),
第一步:(int)a + 1,a为首元素地址,假设此时地址是0x0012ff40,现在被强转成了整数,然后对这个整数进行+1,结果就是0x0012ff41,然后又将这个整数强转成了int*的指针,此时的0x0012ff41就是一个新的地址了,它和原来的数组首地址0x0012ff40相比,它向后走了一个字节(如图ptr2所指向的位置),此时%x打印,应该向后访问四个字节的内容,由于是小端存储,所以数据应该是2000000
第三题:
问题:这是一个二维数组,3行四列,但是由于不是{ { },{ },{ }},而是{()()()},这是一个逗号表达式,保留下来的结果应该是1,3,5。所以这个二维数组应该如图所示:
然后 p = a[0];p是int*,这一步就是将a[0],也就是第一行的首地址赋给了p,所以p现在时第一行数组的首元素地址,然后p[0],也就是*p,所以直接打印出了1。
第四题:
如图所示:
第二问(%d)数组的存储是从低地址到高地址的,p指向的是一个4个整形的一维数组,p+1,p+2,p+3,p+4如图所示,每次跳过四个整形(16字节),所以p [4] [2]应该指向图中&p [4] [2]所对应的位置,此时和&a[4][2]进行相减,其结果的绝对值是中间相差的元素个数,因为以%d打印,所以应该是-4。
第一问(%p),是将-4以%p的形式打印,%p没有符号之分,直接将-4的补码以16进制进行打印
如图所示:-4的原返补码,以及16进制
第五题:
首先第一步char**pa = a; a是一个字符串数组的地址,这个地址被存放进了pa,类型是char**,
如图所示:
因为a是数组名,其代表首元素地址,也就是"work"的地址,然后pa++,它就跳过了首元素,指向了第二个元素,所以结果为 at
第六题:
第一问:*(ptr1 - 1)
首先:int *ptr1 = (int *)(&aa + 1);,这一步&aa取出了整个二维数组的地址,然后+1代表跳过了整个二维数组的地址,如图所示:
图中的红色ptr1就是跳过了二维数组指向的地址。然后此时把这个东西强转成了int*,它的类型从int(*)[2][5],变成了int*,然后以%d的形式打印*(ptr1-1),就是将红色的ptr1往后跳了四个自己,因为此时的红色ptr1是int*,解引用往后跳过4个字节,也就是一个整形的位置,所以指向了10。
第二问:*(ptr2 - 1)
第七题:
已知条件:
将3,4,5语句翻译如下图所示:
第一问 :printf("%s\n", **++cpp);
根据操作符得知从右往左读即可。
第一步:这是一个++cpp前置++,计算就是以++后的结果来计算的,cpp是一个三级指针,它存放的是二级指针数组的地址(cp的首地址),++让它由指向cp的首地址变成了指向cp中的第二个元素。
第二步:此时的一个*,对这个cpp指向的地址(也就是cp中的第二个元素的首地址)进行解引用,得到了cp中的第二个元素的内容c+2。
第三步:而c+2也是一个地址,它指向的是数组c中的第三个元素(如图),此时的最后一个*,对c+2这个地址进行解引用,得到了数组c中的第三个元素的内容,也就是字符串POINT的首地址,此时以%s形式打印,当然是得到POINT这个字符串啦。