源代码:
#include <iostream>
using namespace std;
template <class T>
void printbybit(const T& ob)
{
char* p_e = (char*)&ob;
char* p = p_e + sizeof(T) - 1;
for (; p >= p_e; p--) {
for (int i = 7; i >= 0; i--) {
cout << (((*p) & (1 << i)) ? 1 : 0);
}
}
cout << endl;
}
int main() {
float f;
double d;
cin >> f;
cin >> d;
printbybit(f);
printbybit(d);
return 0;
}
IEEE754标准是什么呢,总结起来就一幅图
值得注意的是,现在我们大多数pc都是小端方式存储数据,就是从右往左分配内存,例如float f是32bit,4byte,内存中是byte4,byte3,byte2,byte1这样存放的
先来看一下实验结果:
1.8转换为二进制是:
1.1100110011001100110011001100110011001100110011001101
对于单精度float类型:
指数部分为:0+127=127:0111 1111
尾数部分为:11001100110011001100110
符号位为:0
与实验结果吻合
## 接下来我们着重解释代码 ##:
char * p_e = (char * )&ob;
这个地方(char *)是强制转换了地址操作的类型,为什么要转换这个呢?这与我们的偏移量有关,这样当指针p进行++或–等操作时,编译器才能确定指针的偏移量。
for (; p >= p_e; p-- )
马上咱们这里就用到了,这看起来好像有点奇怪,但请各位看官回想一下在对一个int类型指针++的时候,是不是指向了下一个int数,所以说类型决定了偏移量,我们之所以要强制转换成char*类型,是因为我们一次刚好移动8bit也就是1byte。
另外大家感到困惑的恐怕就是这里了:
cout << ((( * p) & (1 << i)) ? 1 : 0)
*p我们已经知道是8个bit了,虽然并不会直接显示8bit,但各位需要牢记内存的模样
&是一个与运算,只有同时为1才是1,其他情况为0
1<<i 就是1左移i位。
举个例子好了
运行结果:
1左移1位就是10,2的二进制是10,10&10自然是10,而显示的会是2,所以我们增加一步判断,非零即为1,零就还是0,这对负值也是适用的