This interview question come from a famous communication firm of china. : )

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>
using namespace std; int main()
{
float a = 1.0f; cout << sizeof(int) <<endl;//
cout << sizeof(float) <<endl;// cout << (int)a << endl;//
cout << &a << endl; //(get a's hexadecimal address and is 0012FF7C )
cout << (int)&a << endl;//(int)&a://(cast a's address to decimal integer,1245052 )
cout << (int&)a << endl; }

//(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

  //(int&)a 相当于*(int*)&a ,*(int*)(&a),*((int*)&a) 

 float b = 0.0f;
cout << (int)b << endl;//
cout << &b << endl;
cout << (int&)b << endl;//
cout << boolalpha << ((int)b == (int&)b ) << endl;// 输出true,因为0==0;
return ;
}

到此基本上把单精度在内存的存储方式解决了,不过这只是在X86的小端表示,大端表示方式还得看IEEE给定的标准了。

有关float 数据类型存储方式应该属于较难的一个问题了。: )

what is difference in (int)a,(int&)a,&a,int(&a) ?的更多相关文章

  1. c语言检测文件是否存在int __cdecl access(const char *, int);

    最近写代码,遇到很多地方需要判断文件是否存在的.网上的方法也是千奇百怪,“百家争鸣”. fopen方式打开的比较多见,也有其他各种方式判断文件是否存在的,由于其他方法与本文无关,所以不打算提及. 笔者 ...

  2. int main(int argc,char *argv[])与int main(int argc,char **argv)区别?

    int main(int argc,char *argv[])与int main(int argc,char **argv)区别? 这两种是一个等价的写法 而int main(int argc,cha ...

  3. Number (int float bool complex)--》int 整型、二进制整型、八进制整型、十六进制整型

    # ### Number (int float bool complex) # (1) int 整型 (正整数 0 负整数) intvar = 15 print(intvar) intvar = 0 ...

  4. 字符串转换成整型,到底使用int.Parse,Convert.ToInt32还是int.TryParse?

    当我们想把一个字符串转换成整型int的时候,我们可能会想到如下三种方式:int.Parse,Convert.ToInt32和int.TryParse.到底使用哪种方式呢? 先来考虑string的可能性 ...

  5. ( ( (int(*)(uint, ushort, uint *, uint, int)) (*((uint *)(TCM_BASE + 0x8))) ) (a,b,c,d,e) )

    (  (  (int(*)(uint, ushort, uint *, uint, int))  (*((uint *)(TCM_BASE + 0x8)))  ) (a,b,c,d,e)  ) 首先红 ...

  6. int to string & string to int

    #include "stdafx.h" #include <string> #include <sstream> using namespace std; ...

  7. [转] const int *a与int *const a,const int *const a的区别

    http://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰的位置在 ...

  8. const int *a与int *const a,const int *const a的区别

    来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...

  9. (int)a、&a、(int)&a、(int&)a的区别,很偏僻的题

    (int)a.&a.(int)&a.(int&)a的区别,很偏僻的题 #include <iostream> #include <stdio.h> #i ...

  10. C# int转byte[],byte[]转int

    第一种方法: byte数组转int u = (uint)(b[0] | b[1] << 8 |b[2] << 16 | b[3] << 24); int转byte数 ...

随机推荐

  1. XPath Axes(轴)

    XML 实例文档 我们将在下面的例子中使用此 XML 文档: <?xml version="1.0" encoding="ISO-8859-1"?> ...

  2. 批处理——服务器的web文件备份

    首先建立三个文本文件,稍后会变成.bat结尾的批处理文件. 第一个文件:copyfile.bat[复制需要备份的文件到tmp文件下,等待压缩时使用] xcopy "D:\Webhost\*. ...

  3. C++之路进阶codevs1269(匈牙利游戏)

    1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description ...

  4. Python学习第一天 -- 简单的属性、 语法学习

    1,哈哈哈,是时候来一波Python,其实没办法,最近在做后台的时候,需要用到Python来调试接口,下面是它的简单的语法,权当是记录. 2, #!/user/bin/python # coding= ...

  5. 最好的cpm广告联盟哪里有

    最好的cpm广告联盟哪里有,58传媒广告联盟还要提醒众位站长的是网站在经营发展中必须最大化的扩展自己的优势力量.每个网站都有属于自己的优势魅力,这些优势特点只有得到最大化的发挥才能为网站带来意想不到的 ...

  6. html5 离线存储

    在html页面中引入manifest文件 <html manifest="sample.appcache"> 在服务器添加mime-type text/cache-ma ...

  7. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数017·point点函数

    <zw版·Halcon-delphi系列原创教程> Halcon分类函数017·point点函数 为方便阅读,在不影响说明的前提下,笔者对函数进行了简化: :: 用符号“**”,替换:“p ...

  8. Oracle表结构修改触发视图无法正常使用问题

    一.问题描述 当对视图使用的基表进行表结构修改后,会触发视图的无效以及编译出错问题,必须重建视图解决. 二.问题再现 1.Oracle10g环境 1.1 创建视图测试用两张基表:TestTable和T ...

  9. 【转载】调试利器 autoexp.dat

    转载:http://www.cppblog.com/flyinghare/archive/2010/09/27/127836.html autoexp.dat入门(调试时自定义变量显示) VC在调试状 ...

  10. python之计算器(第四天)

    作业: 使用正则表达式和递归实现计算器功能. 实现: 1.实现带括号的计算 2.实现指数.加减乘除求余等功能 一.实例说明: 本实例自己写了个版本,但依旧存在一点bug,例:-2-2等计算问题,故最后 ...