WParam,LParam,Result三个字段的长度和是12个字节,而WParamLo,WParamHi,LParamLo,LParamHi,ResultLo,ResultHi六个字段之和也是12个字符,同时仔细观察,会发现后面六个字段中的每两个字段与前面三个字段中的每一个字段都是对应的.
再看看
TRect = packed record
case Integer of
0: (Left, Top, Right, Bottom: Longint);
1: (TopLeft, BottomRight: TPoint);
end;
是不是也是一样的呢?
变体记录得作用
(1)节约空间。对于那些要根据条件而决定是否存储得类型,完全可以利用变体记录来达到节约空间得效果。例如,一个公司的员工薪水可以是月薪、年薪等方式,那么并没有必要在记录中都分配空间而又用不到。
(2)类型的转换。例如,如果有一个64位的整数类型作为变体的第一个字段,一个32位的整数Integer类型作为另一个变体的第一个字段,那么可以向64字段赋值然后以整数Integer字段读出其前32位
//假如有这样一个员工登记表
type TpersonRec = record
ID: Integer; {员工编号}
case Boolean of {根据分类}
True: (A: Cardinal); {如果是股东, 登记年薪}
False: (B: Word); {如果不是, 登记日薪}
end;
var
personRec: TpersonRec;
begin
{先算一算这个结构的大小:
ID 是 Integer 类型, 应该是 4 字节大小;
A 是 Cardinal 类型, 也应该是 4 字节大小;
B 是 Word 类型, 应该是 2 字节大小;
合计为 10 个字节.
}
{可事实, TpersonRec 只有 8 个字节}
ShowMessage(IntToStr(SizeOf(TpersonRec))); {8}
{
原因是: 字段 A 和 字段 B 公用了一个储存空间;
当然这个储存空间得依着大的, 是 Cardinal 的尺寸 4 个字节.
}
//赋值测试:
personRec.ID := 110;
personRec.A := 100000; {一看就知道是个股东}
//取值:
ShowMessage(IntToStr(personRec.A)); {100000; 这不可能有错, 十万大洋}
//但是:
ShowMessage(IntToStr(personRec.B)); {34464 ?! 难道这是工人的日薪吗?}
{
首先, A 和 B 两个字段占用同一个空间, 给其中一个赋值, 另一个当然也就有值了;
但因为数据类型的容量不同, 它们的值有可能是不一样的.
在很多情况下, 我们可能根本不去理会另一个值, 但如果的确需要呢?
看下一个例子:
}
end;
type
TpersonRec = record
ID: Integer;
case tag: Boolean of {在这里加了一个 tag 变量}
True: (A: Cardinal);
False: (B: Word);
end;
var
personRec: TpersonRec;
begin
{我们可以用 tag 变量来区分, 记录中变体部