You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++结构体大小异常及与C#转换问题求助

解决Arduino与Unity串口通信的结构体大小不匹配问题

嘿,这个坑我真的见太多人踩过了!你遇到的问题核心原因很明确:在AVR架构的Arduino(比如Uno、Nano这类常用型号)里,double类型其实和float是完全等价的,只占4字节内存,不是你默认以为的8字节。

为啥会这样?因为AVR单片机没有硬件浮点运算单元,GCC编译器为了让浮点运算更快,直接把double实现成了单精度的float——说白了就是个“假的双精度”。这就导致:

  • 你定义的4个double成员,实际是4个4字节的float,加起来16字节,和sizeof(payload)返回的结果完全对得上;
  • 新增一个double后,变成5×4=20字节,也符合这个逻辑。

而Unity的C#环境里,double是标准的8字节双精度类型,两边的内存布局完全对不上,自然解析出来的值全错了。

下面给你几个靠谱的解决办法,按优先级排序:

方法1:统一用float(最推荐,简单高效)

既然Arduino的double本质就是float,不如直接把两端的结构体都改成float,彻底避免混淆:

Arduino端代码修改:

struct SamplePayload { 
  float A; 
  float B; 
  float C; 
  float D; 
} payload;

现在sizeof(payload)会是4×4=16字节,完全符合你的预期。

Unity C#端代码修改:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)] // 强制1字节对齐,消除C#默认填充
struct SamplePayload {
  public float A;
  public float B;
  public float C;
  public float D;
}

一定要加[StructLayout]属性并指定Pack=1,不然C#可能会给结构体加额外的填充字节,导致两边还是对不上。

方法2:强制Arduino用8字节double(不推荐,除非必须)

如果你的项目真的离不开8字节双精度,也可以通过编译选项逼GCC用真正的double,但代价很大——软件模拟双精度运算会让代码变慢、体积变大,AVR本来性能就弱,这么做可能会影响整体运行效率。

要实现的话,在Arduino代码最开头加这两行:

#define __USE_MINGW_ANSI_STDIO 1
#pragma GCC optimize ("-O0") // 关闭优化,避免编译器把双精度优化回单精度

但我真的不建议这么做,除非你有绝对必要的理由。

额外提醒:字节序和校验的小细节

就算解决了结构体大小问题,还要注意字节序:Arduino是小端序,Unity的x86/x64也是小端序,一般不用改,但如果是其他架构(比如某些ARM设备),就得手动转换字节序。

另外,你的LRC校验和一定要基于实际发送的所有字节(头部、载荷大小、载荷)计算,最好在发送前把每个字节打出来,和Unity接收的字节对比,这样能快速定位有没有其他问题。


内容的提问来源于stack exchange,提问作者Heretic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:49:13