(int)a、&a、(int)&a、(int&)a的区别

来源:互联网 发布:守望先锋添加数据索引 编辑:程序博客网 时间:2024/06/05 06:28

double a=1.0f;

cout<<(int&)a<<endl;

 

输出为0

 

 在Turbo c 3.0中的结果都为0;在VC 6.0中为1065353216和0 (int)a是把float型强类型化为int类型,所以为0; (int&)a是把a地址的前两字节当成一个int类型数据输出;至于为什么Turbo c 3.0中的结果为0,可能是因为编译器的差异问题。其实(int&)a就是将a转换为int型的引用如果 int&b=(int&)a; 这样定义的话就好理解了,其实与指针类型转换是一样的。如果a是float型的话输出就不是0了,它将float型的二进制码直接解释为int了。

 

根据IEEE754的浮点数存储格式: 1.0f 在内存中的存储为 0 011 1111 1 000 0000 0000 0000 0000 0000 亦即 0x3F800000 = (1065353216)10 在TC3.0下的结果是0的原因是: TC30下的int型是2个字节的, 所以读的是float类型的低两个字节内容为0. 在TC3.0下用(long &)将还是此结果。对于double也是一样的道理,和存储有关系,double是64位的,把它转换为实际的存储方式是: 0 011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ,这就解释为什么都是0了,vc 6.0下就是低4个字节,为0,同理TC 3.0为低2个字节也为0。

 

 

 

 

 

 

 

float a = 1.0f;

cout < < (int)a < < endl;

cout < < (int&)a < < endl;

cout < < boolalpha < < ( (int)a == (int&)a ) < < endl; // 输出什么?

float b = 0.0f;

cout < < (int)b < < endl;

cout < < (int&)b < < endl;

cout < < boolalpha < < ( (int)b == (int&)b ) < < endl; // 输出什么?

 
 

输出啥?
不明白 (int &)a是啥意识?为啥两个比较的出结果不同。

 
 

—————————————————-

 
 

cout < < boolalpha < < ( (int)a == (int&)a ) < < endl;

// 输出 false, 因为 float  1  int  1 在内存里的表示不一样。


cout < < boolalpha < < ( (int)b == (int&)b ) < < endl; // 输出 true 

// 输出 true, 因为 float  0  int  0 在内存里的表示是一样的。

(int &)a 就表示
不管 a 是什么,我都当他是一个int变量。

从机器码的角度来说,变量a会被翻译成一个内存地址,(int &)a 就是说,这个内存地址里的内容它是一个整数。

 
 

(int)a 呢不同:如果 a 不是整数,就会按规则转换成整数,存入另一个地址(或临时变量)中去。

 
 

浮点数的 1.0f 在内存里是这样表示的:

0011 1111 1000 0000 00000000 00000000

这个32位二进制数被当作整数输出就是:

1065353216

而整数的 1 在内存里是这样表示的:

0000 0000 0000 0000 00000000 00000001

 
 

所以 (int)a != (int&)a 

 
 

浮点的0和整数的在内存里都是:

0000 0000 0000 0000 00000000 00000000 

 
 

所以 (int)b == (int&)b

 
 

 
 

 
 

#include <iostream>

#include <stdio.h>

#include <string.h>

#include <conio.h>

using namespace std;

 
 

int main()

{

float a = 1.0f;

 
 

cout << sizeof(int) <<endl;//4

cout << sizeof(float) <<endl;//4

 
 

cout << (int)a << endl;//1

cout << &a << endl; /* 取a的地址十六进制0012FF7C*/

cout << (int)&a << endl; /*(int)&a:把a的地址强制转换成十进制的整型1245052*/

cout << (int&)a << endl;

/*(int&)a:将a的引用强制转换为整型,意思是a所在的内存,本来定义的时候为float类型,并初始为1.0f,

但现在我要按int类型解释这段内存(也就是说a所在的内存地址中的数据本来是按float型存储表示的,你非要按int型来解释不可)。

1.0f 在内存中的存储为 0011 1111 1000 0000 0000 0000 0000 0000. 把他按整型数解释为2^29+2^28+2^27+2^26+2^25+2^24+2^23=1065353216

 

(int&)a 相当于*(int*)&a ; *(int*)(&a) ; *((int*)&a)

 
 

*/

 

cout << boolalpha << ((int)a == (int&)a ) << endl;// 输出false.因为1!=1065353216.

 
 

float b = 0.0f;

cout << (int)b << endl;//0

cout << &b << endl;/*取b的地址十六进制0012FF78*/

cout << (int&)b << endl;//0

cout << boolalpha << ((int)b == (int&)b ) << endl;// 输出true,因为0==0;

 
 

/*

(int&)a 不经过转换, 直接得到a在内存单元(就是地址)的值

(int)a a在内存中的值转换成int类型

 

float类型在内存中存储的形式是 ,符号位 指数 尾数

由754标准:阶码采用增码(该数补码的反符号),尾数采用原码

所以1.0f 在内存中的形式为

0011 1111 1000 0000 0000 0000 0000 0000

所以输出的是 0x3f800000

0 在内存中的的存储形式

0000 0000 0000 0000 0000 0000 0000 0000

*/

 
 

return 0;

}

 
 

【参考资料】


 

========================c语言中FLOAT 是如何表示的===========================

 
 

c语言中FLOAT 是如何表示的?尾数,阶码是如何在32位上安排的,即哪几位是尾数,哪几位是阶码,那一位是符号位。听说与CPU有关,是真的吗?

 
 

在C++里,实数(float)是用四个字节即三十二位二进制位来存储的。其中有1位符号位,8位指数位和23位有效数字位。实际上有效数字位是24位,因为第

一位有效数字总是"1",不必存储. 有效数字位是一个二进制纯小数。

8位指数位中第一位是符号位,这符号位和一般的符号位不同,它用"1"代表正,用"0"代表负。整个实数的符号位用"1"代表负,"0"代表正。

在这存储实数的四个字节中,将最高地址字节的最高位编号为31,最低地址字节的最低位编号为0,则实数各个部分在这32个二进制位中的分布是这样的:

 

 


注意第一位有效数字是不出现在内存中的,它总是"1"。

 

将一个实数转化为C++实数存储格式的步骤为:

(1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。

(2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边

(3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。

(4)如果实数是正的,则在第31位放入"0",否则放入"1"。

(5)如果n 是左移得到的,说明指数是的,第30位放入"1"。如果n是右移得到的或n=0,则第30位放入"0"。

(6)如果n是左移得到的,则将n减去1然后化为二进制,并在左边加"0"补足七位,放入第29到第23位。

如果n是右移得到的或n=0,则将n(不减1)化为二进制后在左边加"0"补足七位,再各位(指这七位)求反,再放入第29到第23位。

 

或者这么转换:

(1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。

(2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边

(3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。

(4)如果实数是正的,则在第31位放入"0",否则放入"1"。 

(5)如果n 是左移得到的,指数部分为127+n,转换成二进制,放入第30到第23位。

(6)如果n是右移得到的, 指数部分为127-n,转换成二进制,放入第30到第23位。

(7)如果n=0即没有移, 指数部分为127,转换成二进制,放入第30到第23位。

 

 

 

 

将一个计算机里存储的实数格式转化为通常的十进制的格式的方法如下:

(1)将第22位到第0位的二进制数写出来,在最左边补一位"1",得到二十四位有效数字。将小数点点在最左边那个"1"的右边。

(2)取出第29到第23位所表示的值n。当30位是"0"时将n各位求反。当30位是"1"时将n增1。

(3)将小数点左移n位(当30位是"0"时)或右移n位(当30位是"1"时),得到一个二进制表示的实数。

(4)将这个二进制实数化为十进制,并根据第31位是"0"还是"1"加上正号或负号即可。

 

 

 

 
 

特别地,实数0用C++的float格式表示是0000000000000000000000000000000

0。

 
 

 
 

如果还不太明白,这里举几个例子。

一。将23.56化为C++的float格式。

(1)将23.56化为二进制后大约是"10111.1000111101011100001"。

(2)将小数点左移四位,得到"1.01111000111101011100001"。

(3)这已经有了二十四位有效数字,将最左边一位"1"去掉,得到"01111000111101011100001"。将它放入第22到第0位。

(4)因为23.56是正数,因此在第31位放入"0"。

(5)由于我们把小数点左移,因此在第30位放入"1"。

(6)因为我们是把小数点左移4位,因此将4减去1得3,化为二进制,并补足七位得到0000011,放入第29到第23位。

完毕。

如果把最左边定为第31位,最右边定为第0位,那么在C++里,float格式的23.56是这样表示的:01000001101111000111101011100001。相应地-23.56就是这

样表示的:11000001101111000111101011100001。

 
 

二。将实数0.2356化为C++的float格式。

(1)将0.2356化为二进制后大约是0.00111100010100000100100000。

(2)将小数点右移三位得到1.11100010100000100100000。

(3)从小数点右边数出二十三位有效数字,即11100010100000100100000放入第22到第0位。

(4)由于0.2356是正的,所以在第31位放入"0"。

(5)由于我们把小数点右移了,所以在第30位放入"0"。

(6)因为小数点被右移了3位,所以将3化为二进制,在左边补"0"补足七位,得到0000011,各位取反,得到1111100,放入第29到第23位。

完毕。因此0.2356用C++的float格式表示是:00111110011100010100000100100000。其中最左边一位是第31位,最右边一位是第0位。

 
 

三。将实数1.0化为C++的float格式。

(1)将1.0化为二进制后是1.00000000000000000000000。

(2)这时不用移动小数点了,这就是我们在转化方法里说的n=0的情况。

(3)将小数点右边的二十三位有效数字00000000000000000000000放入第22到第0位。

(4)因为1.0是正的,所以在第31位里放入"0"。

(5)因为n=0,所以在第30位里放入"0"。

(6)因为n=0,所以将0补足七位得到0000000,各位求反得到1111111,放入第29到第23位。

完毕。所以实数1.0用C++的float格式表示是:00111111100000000000000000000000。其中最左边一位是第31位,最右边一位是第0位。

 

double同理,只是double是64位。

             符号位   阶码       尾数     长度 
float         1         8          23       32 
double      1         11         52       64 
临时数       1         15         64       80

 

关键是指数部分
float型:31位是实数符号位,30位是指数符号位(127+n、127-n、127),29—23是指数位,22—0位是有效数字位。// 指数占8位

double型:63位是实数符号位,62位是指数符号位(1023+n、1023-n、1023),61—52是指数位,51—0位是有效数字位。// 主指数占11位

0 0
原创粉丝点击