哈哈,这个不是我的经历,听别人说的
据说实习期间是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:这道题值这个价么?
------解决思路----------------------
感觉值这个价格,指针相减和地址相减
------解决思路----------------------
错了,-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 次方,直接就可以通过移位了。移位和除法是有差别的。
而指针我们都会认为是无符号的值,直接移位就可以了,低地址指针减去高地址指针,其实存在回环情况,按有符号的打印是没意义的。