(1)负数在内存中是怎么保存的?
有符号正数的表示方法是最高位代表符号位,0表示正数,1表示负数。比如0000 0011表示3(只用一个字节来示意),
那么-3怎么表示呢?按道理应该是1000 0011,但实际是不是这样的。因为3+(-3)应该=0,看看下面的计算:
0000 0011
+ 1000 0011
=
1000 0110
这个结果显示不是0,二是“-6”。因此,计算机需要一种优雅而简单的方式来表示-3,使得+3后能够=0,所以:
0000 0011
+ ?
=
0000 0000
把3取反后得到了1111 1100,
0000 0011
1111 1100
+
=1111 1111
取反以后得到了全部是1,这也不是0。但是我们知道计算的时候,一旦当最高位溢出的时候,最高位就被丢弃了。全1的
基础上再+1正好把最高位丢弃,其余位全部变成了0。即
0000 0011
1111 1100
0000 0001(+1)
+
=0000 0000
这样就得到了0,所以计算机表示的-3就是1111 1101,即正数二进制取反+1得到的结果,即补码。相反从-3得到+3可通
过-1,取反来得到。
(2)浮点数的表示方法
对于32位的float
符号位(S) 阶码(E) 尾数(M)
1 8 23
看看123.456是怎么表示的,二进制形式: 1111011.01110100101111001 = 1.11101101110100101111001 * 2^6(右移了6
位)
符号位(S) 阶码(E) 尾数(M)
0 00000110 11101101110100101111001
(3)类型扩展(赋值)
小类型到大类型(比如char 到 short),最高位如果是1,则自动扩展填充高位位1,这样扩大了的类型的值仍然没有变
,即:
0111 1111 的负数是 1000 0001 , 当一个字节扩展到两个字节时,发现高位位1 ,扩展得到:1111 1111 1000 0001,
这也是一个负数,通过-1并取反可以得到0000 0000 0111 1111,所以通过这样处理,是数学意义上正确的。
大类型到小类型(比如short到char),直接阶段高位,保留低位。
(4)类型转换
比如 float 转换到 int,或者int转换到float 从(1)(2)可以看得出来,int和float在二进制层面的存储机制是不
一样的,但是:
int i = 4
float f = i
f是多少呢?是4.但是按照二进制来展开并进行4字节直接拷贝的话,f肯定不是4. 所以 位模式不同的情况下,编译器会
进行为模式转换,得到正确的结果。那么,再看看下面的情况:
int i = 3;
float f = *(float*)&i;
这是f就不是3了,编译器就不会对int到float进行位模式转换了,而使直接将i的首地址开始直接拷贝4字节到f的内存,
得到的结果不可预知了。