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

为何Delphi变体记录实际占用内存大于预期值?

问题根源:枚举类型默认大小 + 内存对齐填充

你忽略了两个关键细节:Delphi枚举类型的默认大小是4字节,以及Delphi记录的内存对齐规则会自动插入填充字节,这两者共同导致了记录总大小从你预期的14字节变成了实际的20字节。

1. 枚举类型的默认大小坑

在Delphi中,默认情况下,枚举类型会被编译为Integer类型(32位,4字节),而不是你假设的1字节。你的TDairyItemType没有显式指定大小,所以它占用4字节空间,而非你以为的1字节。

如果想让枚举占用1字节,可以通过两种方式实现:

  • 使用编译器指令:{$Z1},放在枚举定义之前
  • 使用packed关键字定义枚举:packed TDairyItemType = (dtFood, dtRecipe, dtExercise);

2. 内存对齐的填充字节

Delphi会自动为记录字段添加填充字节,确保每个字段的起始地址是其自身大小的整数倍,同时记录的总大小会对齐到最大字段大小的整数倍。我们来一步步拆解你的TDiaryItem的内存布局(默认枚举4字节的情况):

字段大小偏移范围说明
ID40-3起始地址0,符合4字节对齐要求
Positive141字节无需特殊对齐
填充字节15为了让下一个Word类型的GID起始地址是偶数(2的倍数),插入1字节填充
GID26-7起始地址6是偶数,符合Word的对齐要求
ItemType48-11起始地址8是4的倍数,符合4字节枚举的对齐要求
ServID/Time212-13起始地址12是偶数,符合Word的对齐要求
填充字节214-15为了让下一个DWord类型的Serving/Kcal起始地址是4的倍数,插入2字节填充
Serving/Kcal416-19起始地址16是4的倍数,符合DWord的对齐要求

把这些加起来:4+1+1+2+4+2+2+4 = 20字节,正好是你看到的结果。

验证你的空间共享观察

你能通过Item.Time读取到Item.ServID的值,确实说明变体分支共享存储空间——这部分是正确的,问题完全出在枚举大小和内存对齐的填充上。

额外补充:如果修正枚举大小后的情况

即使你把枚举改成1字节,记录总大小也不会是14字节,因为内存对齐仍会插入填充字节,最终总大小会是16字节(对齐到4字节的倍数)。如果想完全消除填充,可以给记录加上packed关键字:packed TDiaryItem = record,这样编译器会取消自动对齐,总大小会变成你预期的14字节(4+1+2+1+6)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 18:27:46