- 今天看到一些关于指针的面试题,真够变态的,有几个题目实际情况中没几个会这样去访问的,但谁让人家面试我们呢…
- 来看看这些场景都怎么回事吧,顺便也提醒自己注意这些时候的指针访问
一维数组指针偏移
分析:
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
↑p |
- 如图,数组是这样存放的。
&a
是一个以5个成员为单位的数组的地址,把这个地址+1就是向后偏移了整个数组的长度,然后给了p指针。 - 针对后一个要打印的
*(p - 1)
,p地址向前偏移1个int单位的地址,取出这个地址的值就是5了。 - 这里的
p
是偏移了整个数组长度之后的地址值。
小端存储,大端访问,会导致数据和预期的值不一样
- 数据存储大小端的概念就不赘述了,简单来说:
- 小端模式: 低地址存放数据低位
- 大端模式: 低地址存放数据高位
分析:
- p1[-1]和上一种情况类似,来看*p2怎么计算的。
(int)a + 1
就是a数组中2所在的位置,现在把2的地址给了p2,再把p2存的地址指向的值取出,而就是取出这个值有点文章。
- 我们知道所有设备,包括windows、linux、Cortex内核等等都有内存的概念,一个待处理的数据放在内存中由于存储模式的不同会造成存放顺序的不同,即有大小端的概念。
- 在linux和一些ARM核32位机中,经过验证都是小端存储的,也就是说题中的数值2在内存中是如下存放的:
内存: (低地址) | 02 | 00 | 00 | 00 | (高地址)
- 我们访问这个地址的值时却不是按照存放的顺序读取的,而是像现在看到的样子拿出来的,于是造成了最终结果和预想的不一样。
二维数组有括号取靠近右括号的数值
- 关于这点我还是挺奇怪的,当时接触到并经过自己尝试后也很惊讶,可能从来没有在应用中碰到这种场景吧。
分析:
- 答案确实是1,我试了下元素不加括号就得到0。这是什么机制呢,如何验证我也不清楚,有没有前辈可以回答呢?
二维数组首地址+1就是加了一个一维数组的整体
分析:
- 后一个
*(p2 - 1)
,a是二维数组的首地址,在这里+1
是代表a[ 0 ]
元素向后偏移一个它的元素大小也就是5个字节,得到的就是6的地址,*(p2 - 1)
就是把6的地址减一个int单位取其值,得到5。
计算机存储补码,十六进制打印地址则为打印存储的补码
- 这和大小端那个有点像,要考虑到硬件底层的原理。
分析:
- 这题需要画出内存中这个数组的排列会比较清晰,能得到第二个要打印的答案:
- p是一个指向只有4个元素的数组指针,所以它每一次偏移就是4个元素而不同于a,是5个元素的数组。
- 图中圈出了题目表示的位置,根据打印的格式化,一个是地址值打印,一个是数值打印,因为是低地址减高地址,得到数值
-4
。 - 而
-4
要表示成存储的地址值,就要注意在计算机中存储的都是数据的补码(关于原因可以自行搜索补充),-4
的32位补码得到就是0XFFFFFFFC。
这些是我比较留心的问题,关于题四那个右括号的问题不知道有没有前辈大神可以解答呢? 期待…