当len的类型为unsigned的时候,首先要明确一点,无符号数是不存在负数的,因此当len = 0时,len - 1的值会是一个很大的正数,例如:
len = 0
假设使用的机器为8为机
补码:[0] + [1] = 0000 0000 + 1111 1111 = 1111 1111
该数的大小为255那么在32位机里这个数就是2的32次方 - 1,这个数极其大
所以会报访问违例地址是0xC0000005
这个错误就是因为访问不了该地址的存储
而当len的类型变为int型时,int都知道是一个有符号的数,他是可以表示的,这样就算用十进制减一下他也是个-1,所以这样,访问就不会报错了。
在现实中计算65535*65535得到的值应该是4,294,836,225
但是在计算机中32位机他的int型数据所能表达的最大正数应该是2^31-1也就是2147483647
因此显然65535*65535得到的结果会溢出,这也就是为什么结果出现的是-131071了
第二个问题
当x=-2147483648,y任意(除-2147483648外)时不成立
为什么不成立,这个还是涉及溢出这个情况
我们知道8位补码所能表达的数的范围是-128~+127
那么32位机补码表达的范围呢是-2147483648~2147483647
如果x = -2147483648那么-x在现实中应该表示成+2147483648
但是这个值超过了32位计算机所表达的值,因此这个条件不成立
***
杨老师还问了个问题
讲:为什么计算机没有人脑算的精确,这其实就是个很好的例子
/* 在堆区申请一块内存 */
int *myarray = (int *) malloc(count*sizeof(int));
在count = 2^30 - 1 的时候,count*sizeof(int)=4这个时
候其所开辟的空间仅仅只有4个字节,这时候进行复制的时候,
其实只对最终一次的复制进行了保存,每次的复制都对前面的进行了覆盖。
先分析代码段1,他的后边已经给出了注释说明
a/-1是进行了去负的优化指令
优化后的结果为1后边31个0实际上和a是一样的
这样或许有点难以理解
那么我们这么来看
假设这是个8位机
他的补码范围是-128~127
a是-128就是1000 0000
进行取反指令按位取反末位加1最后还是
1000 0000也就是-128
他是刚好可以表示位-128的并且没有溢出
当然这个结果并不是我们想要看到的
只是优化后让他躲过了溢出检测才能这样输出
接着我们来看第二段
第二段是地地道道的除法指令
除法的-128/-1显然是+128
因此这不就溢出了么,他不就该讲他溢出了么
这个我知道
第一个代码段显然是比第二个代码段快的
为什么呢
这个涉及到cache的读取机制下面看两个图
在cache中存储的块是按地址顺序存的
第一段的话直接进入一个块挨个读读完进入下一个块
第二段呢这个是进一个块读一个进入下一个块再读一个
读同样多的东西孰快孰慢你是会知道的
当然实际的不会是这样的因为一个块的大小可能可以装很多行,这你自己理解,我学的不扎实