不改变内存数据的强制类型转换

         在嵌入式系统中,无论是什么类型的数据,数据传输一般是以1个字节为单位(8位)。

        比如读取某传感器的温度数据,假设该数据为32位,那么我们用u32来存放最终数据,但是由于一次是以一个字节发送的,所以需要用u8类型的变量作为中间变量,然后通过移位运算来拼接成最终的32位数据。如果发送过来的数据类型为浮点型,该如何正确接收数据呢?

        我们先看一下简单的,非浮点型的例子,代码示意如如下:

u32 dat;
u8 temp;

for(int i=0;i<4;i++)//4个字节,一次8位
{
temp=get_u8_data(); //获取8位数据
dat=dat << 8;  //左移8位
dat = dat | temp; //按位或运算
}

        我们知道,温度数据一般都是小数形式,故此时需要根据温度传感器的数据手册进行换算即可。   

        此处的强制转换,是被传感器厂商所允许的(发过来的u32的数据也是这么设计的)

float temperature = dat *1.2
//被数据数据手册所允许的强制转换,强制转换数据会发生改变,但这样才是正确的温度数据

        假设,传感器发来的数据直接就是float型温度的数据呢?此时不需要公式转换,比如发送过来的温度数据是 float 型的1.23,二进制为0111_0000_1010_0100

        此时如果我们用上述方法,u32 dat 会等于二进制的0111_0000_1010_0100,

        对应的十进制为28836

        此时明显是不对的,假如我们使用强制转换的方法:

u32 dat=28836; //获取到的温度数十进制28836二进制0111_0000_1010_0100
float temperature=(float)dat;

        此时temperature=28836.000,并没有得到1.23!!

        为什么会这样呢,因为强制转换会改变内存数据!比如:

float a=1.23;  //4字节
short unsigned int b;   //4字节
b=a; //强制转换

//a为4字节,当a=1.23时在内存中为0111_0000_1010_0100
//十六进制为70A4,十进制为28836

//若直接强制转换,
//则b=1 ,对应内存为0000_0000_0000_0001

        我们看到,float a=1.23转换成short unsigned int b之后,b=1;

        二进制数据由0111_0000_1010_0100变为0000_0000_0000_0001

       有什么办法将u32的二进制数据赋值给 folat 呢?首先,很容易想到的,位运算符

u32 get_dat=28836;//代表了float型数据1.23,二进制0111_0000_1010_0100
float temperature ;
temperature = temperature | get_dat;

        哈哈,这不就将get_dat的二进制数据赋值给float temperature了嘛,

        此时的temperature=0111_0000_1010_0100

        打印temperature得到的数就是1.23.

        如果你这么想,编译器会将你打回现实,因为float型的数据不允许使用位运算符!

        怎么办呢?我们可以用指针!既然数据强制转换会丢失,那我将数据地址强制转换呢?!

u32 get_dat=28836; //这是接收到的温度数据,二进制0111_0000_1010_0100
float *temperature;
temperature=(float *)&get_dat;

        我们将u32 get_dat的地址强制转换成float *

        此时就是temperature和get_dat共用一块内存,其二进制数据当然是一样的.

        此时的*temperature=1.23

        至此,大功告成!

        但是需要注意的是,指针强制转换需要指针长度一致,本例中float和u32都是4个字节。如果不一致的话就需要再定义一个中间变量,避免发生严重错误。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值