话不多说,先上代码
inline void printfloat_16(const float fnum){
uint8_t* c = (uint8_t*)&fnum; //指针指向低位字节的地址,所以最先传给c的是低位字节
printf("0x");
for(auto i = 3;i >= 0;i--)
printf("%02x",c[i]); //先获得的是低位字节,所以应该把低位字节放在最后面
}
这个知识点困扰了作者很久,之所以分享出来,是因为这部分有很多细节很容易让人迷糊,接下来依次进行总结:
1.为什么不能直接printf()打印浮点数的十六进制呢?
~~~~~~~~~
很多人(包括作者自己)可能会觉得,float的十六进制表示与unsigned int的十六进制表示没什么不同,不管在64位机还是32位机下,二者都是占四个字节,所以可以直接将float强转为uint32_t,然后printf(“%x”,)打印出来不就好了嘛。
~~~~~~~~~
但是,有一点很容易被忽略
~~~~~~~~~
就是,uint32_t是整型,无法表示出float中带的小数位,所以强转之后再打印就看不到小数位了,例如:
int main(int argc,char* argv[]){
float a = 0.0015f; //(0x3ac49ba6)
printf("0x%x \r\n",(uint32_t)a);
}
~~~~~~~~~ 打印的结果是:
0x0
~~~~~~~~~ 所以,小数点后的数直接被全盘忽略
2.指针指向一个多字节(大于一个字节)的数据类型的变量时,指针中存储的是其最低字节的地址
~~~~~~~~~
由于我写的这个打印函数,是将要打印的浮点数看作一个数组,依次取出其各个字节的数据(float是4个字节,所以看作一个四个元素的unsigned char类型的数组)。
~~~~~~~~~ 那么,这个取值的顺序就变得尤为关键了,那么到底是先取的低位字节还是先取的高位字节呢?
~~~~~~~~~
既然我是用指针去取,那么就要看一开始指针指向的是高位还是低位。
~~~~~~~~~
这篇文章详细的测试了为什么指针指向的最低位字节,有兴趣的朋友可以看一看。
指针指向变量的最低字节
3.打印的顺序要反过来
~~~~~~~~~
前面提到,指针会先把变量的最低位字节取出来,那么我们在打印的时候,就要反着打印,把最后取出的最高位字节打印出来,否则会让自己迷糊很久(作者当时就纠结在这里还以为是大端与小端的问题)