题目:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main() {
float a =1.0f;
cout << (int)a << endl;
cout << &a << endl;
cout << (int&)a << endl;
cout << ((int)a == (int&)a ) << endl;
float b =0.0f;
cout << (int)b << endl;
cout << &b << endl;
cout << (int&)b << endl;
cout << ((int)b == (int&)b ) << endl;
return 0;
}
输出:
1
0x7ffef73dcca0
1065353216
0
0
0x7ffef73dcca4
0
1
主要解释(int&)b:
float a = 1.0f根据IEEE R32.24标准对32位浮点数采用的表示为:
数符(1位)|指数(8位) | 尾数(23位)
数符:0
指数:127+0=127 01111111
尾数:0
内存中整数1就是0 01111111 0000000 00000000 00000000
转换为十进制:1065353216
float b = 0.0f根据IEEE R32.24标准对32位浮点数采用的表示为:
数符(1位)|指数(8位) | 尾数(23位)
数符:0
指数:0
尾数:0
内存中整数1就是0 00000000 0000000 00000000 00000000
转换为十进制:0
所以可以得到编译器的输出结果
理论知识:
首先呢,我们来看一下浮点数的格式:
float是单精度32位,所以呢:
符号位 (Sign):0代表正数,1代表为负数;
指数位 (Exponent):用于存储科学计数法中的指数数据,指数的数值要加上127,如果指数本来是3,那么要换成130来存储;
尾数部分 (Mantissa):采用移位存储尾数部分,因为M的值一定是1<= M <2,所以它绝对可以写成1.xxxxxxx的形式,所以规定M在存储时舍去第一个1,只存储小数点之后的数字,这样做节省了空间。
举例子:
用二进制的科学计数法表示 1000.1,可以表示为1.0001 * 23
用二进制的科学计数法表示 1110110.1,可以表示为1.1101101 * 26
任何一个数的科学计数法表示都为1. xxx * 2n ,尾数部分就可以表示为xxxx,由于第一位都是1嘛,干嘛还要表示呀?所以将小数点前面的1省略。
举个例子,浮点数-3.75,先将其转换成2进制的,则为-11.11,可以写成-1.111*2^1,所以符号位是1,加127等于128,指数位是1000 0000,尾数位是111 0000 0000 0000 0000 0000(就是3个1,然后后面20个0,一共23位)。
11000 0000 111 0000 0000 0000 0000 0000
那么1.75呢?1.75写成二进制就是1.11*2^0,所以符号位是0,指数位0+127=127,是0111 1111,尾数位是110 0000 0000 0000 0000 0000(2个1,后面21个0,一共23位),把这几部分写在一起就是:
0011 1111 1110 0000 0000 0000 0000 0000
这个浮点数,在内存里存储的格式就是这样。如果我们把它当做整数来读取,那会是多少呢?
输出为:1071644672
是不是感觉很巧啊,哈哈,发现点什么了嘛?
(int)x 强制类型转换,是将浮点数x为参数构造整数(即float转换为int)
(int &)y 则是告诉编译器将y看成int对待(内存里的数据不做任何转换),所以(int &)x值为1071 644 672。
至于(int)的话,我就不多说啦,就是强制转换成整型指针,一般人们容易混淆的是(int)和(int&)这两个。
补充:浮点数0.0是比较特殊的,它并不按照上面说的浮点数的格式存储,浮点数0.0在内存里的存储是000…000(全零)。