【问题标题】:Converting struct to byte and back to struct将结构转换为字节并返回结构
【发布时间】:2012-11-26 09:17:42
【问题描述】:

我目前正在使用Arduino Unos、9DOF 和XBees,我正在尝试创建一个可以逐字节串行发送的结构,然后重新构建为一个结构。

到目前为止,我有以下代码:

struct AMG_ANGLES {
    float yaw;
    float pitch;
    float roll;
};

int main() {
    AMG_ANGLES struct_data;

    struct_data.yaw = 87.96;
    struct_data.pitch = -114.58;
    struct_data.roll = 100.50;

    char* data = new char[sizeof(struct_data)];

    for(unsigned int i = 0; i<sizeof(struct_data); i++){
        // cout << (char*)(&struct_data+i) << endl;
        data[i] = (char*)(&struct_data+i); //Store the bytes of the struct to an array.
    }

    AMG_ANGLES* tmp = (AMG_ANGLES*)data; //Re-make the struct
    cout << tmp.yaw; //Display the yaw to see if it's correct.
}

来源:http://codepad.org/xMgxGY9Q

这段代码似乎不起作用,我不确定我做错了什么。

我该如何解决这个问题?

【问题讨论】:

  • 对所有 c++ 程序员的恳求 - 使用 c++ 样式转换而不是 c 样式转换。
  • 没有意识到他们是 c 风格的演员,因为这是我的老师在我的 C++ 课上教我的

标签: c++ struct byte arduino xbee


【解决方案1】:

始终充分利用数据结构..

union AMG_ANGLES {
  struct {
    float yaw;
    float pitch;
    float roll;
  }data;
  char  size8[3*8];
  int   size32[3*4];
  float size64[3*1];
};

【讨论】:

  • 为什么浮点数是 8 个字节?
  • 不是。浮点数是 32 位的。但是有double,它基本上只是一个64位浮点数。还有长双。
【解决方案2】:

看来我已经用下面的代码解决了我的问题。

struct AMG_ANGLES {
    float yaw;
    float pitch;
    float roll;
};

int main() {
    AMG_ANGLES struct_data;

    struct_data.yaw = 87.96;
    struct_data.pitch = -114.58;
    struct_data.roll = 100.50;

    //Sending Side
    char b[sizeof(struct_data)];
    memcpy(b, &struct_data, sizeof(struct_data));

    //Receiving Side
    AMG_ANGLES tmp; //Re-make the struct
    memcpy(&tmp, b, sizeof(tmp));
    cout << tmp.yaw; //Display the yaw to see if it's correct
}

警告:此代码仅在发送和接收使用相同的endian 架构时才有效。

【讨论】:

  • 除了您的警告之外,双方还需要以相同的方式表示一个浮点数。我建议将其作为定点整数发送(在上面的示例中:8796、-11458、10050)并记录值的字节顺序。使用 endian.h 中的 htobe32() 等函数在主机和大端或小端之间进行转换。
  • @Steven10172 结构不能有填充吗?这不会紧紧地包装结构。
【解决方案3】:
for(unsigned int i = 0; i<sizeof(struct_data); i++){
    // +i has to be outside of the parentheses in order to increment the address
    // by the size of a char. Otherwise you would increment by the size of
    // struct_data. You also have to dereference the whole thing, or you will
    // assign an address to data[i]
    data[i] = *((char*)(&struct_data) + i); 
}

AMG_ANGLES* tmp = (AMG_ANGLES*)data; //Re-Make the struct
//tmp is a pointer so you have to use -> which is shorthand for (*tmp).yaw
cout << tmp->yaw; 
}

【讨论】:

  • 哪种解决方案更有效?你的还是我的?此操作将每秒运行约 30-50 次
  • memcpy 可能更有效。所以,我会选择你的解决方案。它还使代码更易于阅读。
  • 感谢您解释为什么我必须使用 -> 我还是 C++ 新手,2-3 个月前才开始学习,所有 * 和 & 有时仍然让我感到困惑跨度>
  • 是的,指针是 C 和 C++ 初学者必须清除的经典障碍。至于为什么 memcpy 更高效,看看this question
【解决方案4】:

你做事的顺序不对,表达方式

&struct_data+i

获取struct_data的地址并将其增加i结构大小的倍

试试这个:

*((char *) &struct_data + i)

这会将struct_data 的地址转换为char * 并且然后 添加索引,然后使用解引用运算符(一元*)获取该地址处的“char” .

【讨论】:

  • 它似乎不让我调用它。我收到“第 23 行:错误:在 'tmp' 中请求成员 'yaw',它属于非类类型 'AMG_ANGLES*'”
  • 看我的回答。你必须使用'->'
  • 这在 6 年后的今天帮助很大。谢谢好心的先生!
猜你喜欢
  • 2011-02-11
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
相关资源
最近更新 更多