标签:
This interview question come from a famous communication firm of china. : )
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <conio.h> 5 using namespace std; 6 7 int main() 8 { 9 float a = 1.0f; 10 11 cout << sizeof(int) <<endl;//4 12 cout << sizeof(float) <<endl;//4 13 14 cout << (int)a << endl;//1 15 cout << &a << endl; //(get a‘s hexadecimal address and is 0012FF7C ) 16 cout << (int)&a << endl;//(int)&a://(cast a‘s address to decimal integer,1245052 ) 17 cout << (int&)a << endl; 18 19 }
//(int&)a:将a的引用强制转换为整型,意思是a所在的内存,本来定义的时候为float类型并初始为1.0f,但现在我要按int类型解释这段内存(也就是说a所在的内存地址中的数据本来是按float型存储表示的,你非要按int型来解释不可.
1.0f
在内存中的存储为
0
011
1111
1
000
0000
0000
0000
0000
0000.
把他按整型数解释为2^29+2^28+2^27+2^26+2^25+2^24+2^23=1065353216
看懂上面的转换需要具备下面几个知识点:
1、关于十进制小数转二进制
具体为小于1的小数(如0.5)乘2取整法,如0.5的二进制为0.5*2=1,取整数1,故二进制为0.1。12.5的二进制为12(2)+0.5(2)=1100.1
2、关于浮点数在内存中的存储方式
在存储方式上,float,double和整数的存储方式不同,整数在内存中属于顺序存储方式,虽有大端小端之分,但是存储是顺序的。但是单精度和双精度却不是以顺序存储方式存储而是按照一定的标志IEEE来实现的,都有各自的标志编码方式:
浮点型变量在计算机内存中占用4字节(Byte),即32-bit。遵循IEEE-754格式标准。一个浮点数由2部分组成:底数m 和 指数e。
±mantissa × 2^exponent
(注意,公式中的mantissa 和 exponent使用二进制表示)
如一个单精度数12.5在内存中可表示为,12.5(2)=1100.1=1.001*23
底数部分 使用二进制数来表示此浮点数的实际值。
指数部分 占用8-bit的二进制数,可表示数值范围为0-255。但是指数应可正可负,所以IEEE规定,此处算出的次方(即是来自内存存储的内容,存储指数)须减去127才是真正的指数(实际的指数,如12.5转换为二进制为:1100.100=1.100100*23, 3即为实际指数)。所以float的指数可从 -126到128.
底数部分实际是占用24-bit的一个值,由于其最高位始终为1,所以最高位省去不存储,在存储中只有23-bit。到目前为止,底数部分23位加上指数部分8位 使用31位。那么前面说过,float是占用4个字节即32-bit, 那么还有一位是干嘛用的呢? 还有一位,其实就是4字节中的最高位,用来指示浮点数的正负,当最高位是1时,为负数,最高位是0时,为正数。
也就是说我们可以认为float在小端CPU的编码方式应该是:
31<-------------------------------------------------0
S(1bit)| E(8bits)| M(23bits) |
即:
-----------------------------------------------------
ADDR0+3 ADDR0+2
ADDR0+1
ADDR0
SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
-----------------------------------------------------
S: 表示浮点数正负,1为负数,0为正数。
E: 指数加上127后的值的二进制数
M: 24-bit的底数(只存储23-bit)
然而值得注意的是,浮点数为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。当然,这个特例也不用认为去干扰,编译器会自动去识别。
到此,1.0f在内存中的二进制表示为1.0(2)=1.0在内存中的存储为:0 011 1111 1000 0000 0000 0000
0000 0000=0x3f800000
把他按整型数解释为2^29+2^28+2^27+2^26+2^25+2^24+2^23=1065353216
1 //(int&)a 相当于*(int*)&a ,*(int*)(&a),*((int*)&a) 2 3 float b = 0.0f; 4 cout << (int)b << endl;//0 5 cout << &b << endl; 6 cout << (int&)b << endl;//0 7 cout << boolalpha << ((int)b == (int&)b ) << endl;// 输出true,因为0==0; 8 return 0; 9 }
到此基本上把单精度在内存的存储方式解决了,不过这只是在X86的小端表示,大端表示方式还得看IEEE给定的标准了。
有关float 数据类型存储方式应该属于较难的一个问题了。: )
what is difference in (int)a,(int&)a,&a,int(&a) ?
标签:
原文地址:http://www.cnblogs.com/Koestler/p/5141532.html