当前位置: 代码迷 >> 驱动开发 >> (见习7.2k)面试就这么一道题指针,郁闷了
  详细解决方案

(见习7.2k)面试就这么一道题指针,郁闷了

热度:118   发布时间:2016-04-28 10:04:27.0
(实习7.2k)面试就这么一道题指针,郁闷了
哈哈,这个不是我的经历,听别人说的
据说实习期间是7.2k的岗
题目看了一下,只是知道一定与数据类型和对齐有关(地址相差17,数据类型时8字节,那么答案要么都是2,要么都是3)但是细节上面回答不出为什么两个数的绝对值不等。

大概是这样:
#include<stdio.h>
#include<stdlib.h>
int main()
{
    double *p1=(double*)100;
    double *p2=(double*)117;
    printf("%d\n",p1-p2);
    printf("%d\n",p2-p1);
}
答案是:
?-3
2
向各位求解了。。。
ps:这道题值这个价么?
------解决思路----------------------
感觉值这个价格,指针相减和地址相减
------解决思路----------------------
引用:
Quote: 引用:

为啥会用到sar?

”sar eax,3“,(右移3位)相当于eax/8。
double floating point 的是8bytes。所以,p1和p2相减结果除以8才是两个指针间可容纳double floating point 的数量。



错了,-17 / 8 的结果一般是-2 余 -1 (参考《c陷阱与缺陷》7.7除法运算时发生的截断)
这个题真的蛮让人无语的,编译器似乎会检测数据类型的大小。这里sizeof(float)= 8正好是2的次幂,所以使用sar。如果sizeof(某个结构体)不等于2的次幂,就会用除法。
用除法和位移的结果明显不同,我实测了一个大小为7的结构体。
int main()
{
    S *p1=(S*)100;
    S *p2=(S*)117;
cout<<sizeof S<<endl;
    printf("%d\n",p1-p2);
    printf("%d\n",p2-p1);
return 0;
}

7
-2
2


我是没明白编译器为啥要这么做,个人猜测是个未定义行为,恐怕要请教熟悉协议的大牛了。
------解决思路----------------------
这么看来就是因为用了移位指令,而没有用除法指令,所以计算的绝对值不一样。
如果用除法指令,应该是 -2 和 2

我在linux下用gcc编译,做了如下测试:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    printf("-17/8    =%d \n",(-17)/8);
    printf("-17>>3=%d \n",(-17)>>3);
    return 0;
}
得出的结果是
-17/8    =-2 
-17>>3=-3 

我们假如-17或17装在一个才8bit里面来计算右移的操作
17的补码是:
0001 0001
那么17/8用17>>3右移3位来代替那么结果是:
000 0010  ->显然结果是 2
 
-17 的原码是   1001 0001
           反码是   1110 1110
          补码是    1110 1111
计算机是用补码计算的,那么-17/8用(-17)>>3右移代替则:
1110 1111 -->右移3位后是--->  1111 1101
而补码111 1101就是 -3 
------解决思路----------------------
也就是是说 -17/8除法的实现不全是通过 -17>>3即算数右移实现的~
可以看一下下面的链接~
http://blog.csdn.net/sunnylgz/article/details/17584507

------解决思路----------------------
在编译器认为,如果是有符号的值做除法,即使是 2 的 N 次方,也会通过相关措施得到正确的值,如 -17 / 8 = -2;
如果是无符号的值,遇到 2 的 N 次方,直接就可以通过移位了。移位和除法是有差别的。
而指针我们都会认为是无符号的值,直接移位就可以了,低地址指针减去高地址指针,其实存在回环情况,按有符号的打印是没意义的。
  相关解决方案