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

TwinCAT 3调用SizeOf获取结构体大小返回值与预期不符问题

现象原因

该现象是结构体内存对齐机制导致的,这是编译器为了提升CPU内存访问效率的默认行为,遵循两个核心规则:

  • 结构体中每个成员的起始偏移地址,必须是该成员自身类型大小的整数倍
  • 结构体整体的总大小,必须是结构体内部最大基础成员类型大小的整数倍

你的结构体中存在占4字节的UDINT类型成员,是整个结构体里最大的基础类型,因此结构体总大小必须是4的整数倍。你的成员累加总大小为14,并非4的整数倍,编译器会自动在结构体末尾填充2个空字节,将总大小补到符合要求的16字节,和你测试的结果完全吻合。
对应你另外两个测试场景也完全符合对齐规则:

  • 将UDINT替换为占2字节的UINT后,结构体最大基础类型变为2字节,14是2的整数倍,无需额外填充,大小符合预期
  • 将UDINT调整到结构体末尾时,UDINT的起始偏移必须是4的整数倍,前面成员累加总大小为10,不符合4的倍数要求,因此编译器会在iCrateCnt成员后填充2字节凑到12,再存放4字节的UDINT,总大小仍为16
解决方法

如果需要取消内存对齐,让结构体大小等于所有成员累加的实际大小,可以使用编译器提供的强制对齐指令:

  • GCC/Clang环境:在结构体定义上添加__attribute__((packed))属性,示例如下:
typedef struct __attribute__((packed)) {
    UINT iStation;
    UINT iLayer;
    UDINT iReserve;
    UINT iPos;
    UINT iRow;
    UINT iCrateCnt;
} MyStruct;
  • Visual Studio环境:使用#pragma pack指令包裹结构体定义,示例如下:
#pragma pack(push, 1) // 设置按1字节对齐,同时保存原有对齐配置
typedef struct {
    UINT iStation;
    UINT iLayer;
    UDINT iReserve;
    UINT iPos;
    UINT iRow;
    UINT iCrateCnt;
} MyStruct;
#pragma pack(pop) // 恢复原有对齐配置

注意:关闭内存对齐会降低CPU访问结构体成员的性能,部分嵌入式架构(如ARM)还可能触发未对齐访问的硬件异常,非特殊需求不建议直接关闭对齐。如果只是要减少内存浪费,优先通过调整成员顺序(将相同大小的成员集中排列,大尺寸成员放在最前)来减少填充字节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:24:07