首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将浮动分离为4 uint8_ts,然后合并回一起

将浮动分离为4 uint8_ts,然后合并回一起
EN

Stack Overflow用户
提问于 2022-12-01 23:41:30
回答 3查看 83关注 0票数 1

我正在开发RF连接的客户端(C)和服务器端(C++)。我需要发送一个浮点值,但是在架构的设置方式中,我必须将我的消息安排在一个结构中,这个结构将我限制为3个uint8t参数: p0、p1、p2。我的解决方案是将浮点数分解为一个4 uint8_ts的数组,并发送2条单独的消息,并使用p0作为标识符,无论消息包含前半部分还是下半部分。

到目前为止,我有这样的事情:

服务器(C++):

代码语言:javascript
复制
sendFloat(float f)
{
   messageStruct msg1, msg2;
   uint8_t* array = (uint8_t*)(&f);

   msg1.p0 = 1; //1 means it's the first half
   msg1.p1 = array[0];
   msg1.p2 = array[1];

   msg2.p0 = 0; //0 means it's the second half
   msg2.p1 = array[2];
   msg2.p2 = array[3];

   sendOverRf(msg1);
   sendOverRf(msg2);
}

客户(C):

代码语言:javascript
复制
processReceivedMessage (uint32_t id, uint32_t byteA, uint32_t byteB) //(p0,p1,p2) are routed here
{
   static uint32_t firsHalfOfFloat;
   uint32_t ondHalfOfFloat;
   float combinedFloat;
   
   if(id == 1) //first half
   {
       firstHalfOfFloat = (byteA << 8) | byteB;
   }
   else        //second half
   {
       secondHalfOfFloat = (byteA << 8) | byteB;
       combinedFloat = (float)((firstHalfOfFloat << 16) | secondHalfOfFloat);
   }
  
    writeFloatToFile(combinedFloat);
}  

然后,客户端必须根据请求将浮点数发回。

客户(C):

代码语言:javascript
复制
sendFloatBack(uint8_t firstHalfIdentifier) // is commanded twice by server with both 0 and 1 ids
{
    messageStruct msg;
    float f = getFloatFromFile();
    uint8_t* array = (uint8_t*)(&f);
    
    msg.p0 = firstHalfIdentifier;

    if(firstHalfIdentifier == 1) //First half
    {
        msg.p1 = array[0];
        msg.p2 = array[1];       
    }
    else                         //Second half
    {
        msg.p1 = array[2];
        msg.p2 = array[3];  
    }
    
    sendOverRf(msg);
}

最后,服务器(C++)获取该值:

代码语言:javascript
复制
retrieveFunc()
{
    float f;
    uint32_t firstHalf;
    uint32_t secondHalf;
        
    messageStruct msg = recieveOverRf();
    firstHalf = (msg.p1 << 8) | msg.p2;
    msg = receiveOverRf();
    firstHalf = (msg.p1 << 8) | msg.p2;
    f = (firstHalf << 16) | secondHalf;  
}

但我的价值观是错误的。任何帮助都会很好。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-12-02 00:44:40

联合是一种非常方便的方法,可以将float分解为单个字节,然后再将字节重新组合在一起。下面是一些示例代码,展示了如何做到这一点:

代码语言:javascript
复制
#include <stdio.h>
#include <stdint.h>

typedef union {
   uint8_t _asBytes[4];
   float   _asFloat;
} FloatBytesConverter;

int main(int argc, char** argv)
{
    FloatBytesConverter fbc;
    fbc._asFloat = 3.14159;

    printf("Original float value is:  %f\n", fbc._asFloat);

    printf("The bytes of the float are:  %u, %u, %u, %u\n"
       , fbc._asBytes[0]
       , fbc._asBytes[1]
       , fbc._asBytes[2]
       , fbc._asBytes[3]);

    // Now let's put the float back together from the individual bytes
    FloatBytesConverter ac;
    ac._asBytes[0] = fbc._asBytes[0];
    ac._asBytes[1] = fbc._asBytes[1];
    ac._asBytes[2] = fbc._asBytes[2];
    ac._asBytes[3] = fbc._asBytes[3];

    printf("Restored float is %f\n", ac._asFloat);

    return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2022-12-02 00:00:50

是你的朋友。

代码语言:javascript
复制
float toFloat(const uint8_t *arr)
{
    float result;

    memcpy(&result, arr, sizeof(result));

    return result;
}

uint8_t *toArray(const float x, uint8_t * const arr)
{
    memcpy(arr, &x, sizeof(x));
    return arr;
}
代码语言:javascript
复制
void sendFloat(float f)
{
   messageStruct msg1, msg2;
   uint8_t array[4];

   toArray(f, array);

   msg1.p0 = 1; //1 means it's the first half
   msg1.p1 = array[0];
   msg1.p2 = array[1];

   msg2.p0 = 0; //0 means it's the second half
   msg2.p1 = array[2];
   msg2.p2 = array[3];

   sendOverRf(msg1);
   sendOverRf(msg2);
}
代码语言:javascript
复制
float retrieveFunc(void)
{
    float f;
    unit8_t array[4]
        
    messageStruct msg = recieveOverRf();
    array[0] = msg.p1;
    array[1] = msg.p2;
    msg = receiveOverRf();
    array[2] = msg.p1;
    array[3] = msg.p2;
    return toFloat(array);
}
票数 0
EN

Stack Overflow用户

发布于 2022-12-02 00:35:11

就体系结构而言,字节就是字节。

我们假设双方都使用IEEE 754 (或其他什么)。

我们可以将一个float (4个字节)放入/输出一个带有memcpyuint32_t

但是,我们必须处理处理器的缺陷。

编辑:

的问题是,p0,p1,p2都是uint8_ts。- TheBigJabronie

噢,我的错。我已经更新了代码,只使用了我在下面留下的原始/不正确的答案,以供参考。

这是更新的代码。这些函数将在任何一个主机上工作,而不考虑每个体系结构的功能。

注意,您的主要问题是float的编码。因此,下面的代码假设数据包完好无损地到达(即重试/重发是在较低的RF层完成)。

代码语言:javascript
复制
void
sendFloat(float f)
{
    messageStruct msg;
    uint32_t i32;

    assert(sizeof(float) == sizeof(uint32_t));

    // get bytes of the float in native endian order
    memcpy(&i32,&f,sizeof(i32));

    // handle endianness
    i32 = htonl(i32);

    // send MSW half
    msg.p0 = 1;
    msg.p1 = i32 >> 24;
    msg.p2 = i32 >> 16;
    sendOverRf(msg);

    // send LSW half
    msg.p0 = 2;
    msg.p1 = i32 >> 8;
    msg.p2 = i32 >> 0;
    sendOverRf(msg);
}

float
recvFloat(void)
{
    uint32_t i32 = 0;
    float f;

    messageStruct msg;

    // NOTE: the two packets _should_ come in the same order as the sender, but
    // we'll handle out of order packets to be complete
    for (int rcount = 0;  rcount < 2;  ++rcount) {
        msg = recieveOverRf();

        uint32_t tmp = msg.p1;
        tmp <<= 8;
        tmp |= msg.p2;

        switch (msg.p0) {
        case 1:
            i32 |= tmp << 16;
            break;
        case 2:
            i32 |= tmp << 0;
            break;
        }
    }

    // handle endianness
    i32 = ntohl(i32);

    // get bytes into float
    memcpy(&f,&i32,sizeof(float));

    return f;
}

我的原始代码和进一步的假设。

我们可以在一条信息中做到这一点,并留出足够的空间。

这是我要用的代码。

代码语言:javascript
复制
void
sendFloat(float f)
{
    messageStruct msg;
    uint32_t i32;

    assert(sizeof(float) == sizeof(uint32_t));

    // get bytes of the float in native endian order
    memcpy(&i32,&f,sizeof(i32));

    // handle endianness
    i32 = htonl(i32);

    // means we're sending a float
    msg.p0 = CMD_FLOAT;
    msg.p1 = i32;
    msg.p2 = 0;

    sendOverRf(msg);
}

float
recvFloat(void)
{
    uint32_t i32;
    float f;

    messageStruct msg = recieveOverRf();

    // ensure we got correct message
    if (msg.p0 != CMD_FLOAT)
        exit(1);

    // get int in network order
    i32 = msg.p1;

    // handle endianness
    i32 = ntohl(i32);

    // get bytes into float
    memcpy(&f,&i32,sizeof(float));

    return f;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74649350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档