小问题,进来看看..(0分)

  • 主题发起人 主题发起人 linuxping
  • 开始时间 开始时间
L

linuxping

Unregistered / Unconfirmed
GUEST, unregistred user!
经常看见这样的定义:
TInAddr = packed record
case integer of
0: (S_un_b: SunB);
1: (S_un_w: SunW);
2: (S_addr: u_long);
end;
把integer拿出来做选择?integer会等于1? 2? 3? 不解!
 
integer默认应该是0吧
 
今天再看到自己的贴子,突然有点想法:
这是个'联合体'的定义....
'联合体'大小为integer,
0,1,2 三个选项共用integer大小的存储空间

不知道对不?
 
首先说 packed record 这个是不定长记录也就是说通过具体的内容来决定。
packed 表示不align,就是不对齐,所有元素都紧密排列
非packed的record,就是align了的,为了访问的速度,对元素的起点进行了对齐的处理
比如,
type t= record
a:char;
b:smallint;
end;
如果b开始于2的倍数的地址,存取速度会比较快
所以它从字节2开始存放,而a从0开始,字节1就没用上,是个空洞
整个record占用4个字节

type t=packed record
a:char;
b:smallint;
end;
不进行对齐,b直接跟在a后面,从字节1开始存放
整个record占用3个字节,但是存取速度会慢一点。

下面再说 case integer of 在这里相当与 C 中的 union 属于变体记录。
记录中的变体部分包含几个变体,在内存中它们共享相同的空间。可以在任何时候对记录中任何变体的任何字段读或写;但如果在一个变体中写一个字段并且在另一个变体中写另一个字段,那么后面的写操作可能覆盖前面写入的数据
变体部分有两种用途。首先,假设要创建一个记录类型,它有不同数据种类的字段,但不需要在单个记录实例中使用全部数据。例如,

type

TEmployee = record

FirstName, LastName: string[40];

BirthDate: TDate;

case Salaried: Boolean of

True: (AnnualSalary: Currency);

False: (HourlyWage: Currency);

end;

这里的意思是,每个雇员都有年薪或计时工资,但不能都有。因此,在创建TEmployee时,没有理由为两个字段都分配足够的内存。这种情况下,变体之间只有名字不同,而要想让字段的类型不同也是很容易的。考虑相对复杂的例子:

type

TPerson = record

FirstName, LastName: string[40];

BirthDate: TDate;

case Citizen: Boolean of

True: (Birthplace: string[40]);

False: (Country: string[20];

EntryPort: string[20];

EntryDate, ExitDate: TDate);

end;

type

TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);

TFigure = record

case TShapeList of

Rectangle: (Height, Width: Real);

Triangle: (Side1, Side2, Angle: Real);

Circle: (Radius: Real);

Ellipse, Other: ();

end;

对上面的每个记录实例,编译器分配足够的内存以在最大的变体中能够保存所有的字段。可选的Tag和常量列表constantLists(如上面最后一个例子中Rectangle、Triangle等)在编译器管理字段的途径中不扮演任何角色,它们仅为程序员提供方便。


变体部分的第二个用途是,可以将相同的数据视为不同的类型,尤其在编译器不允许类型转换的情况。例如,如果有一个64位的实数Real类型作为变体的第一个字段,一个32位的整数Integer类型作为另一个变体的第一个字段,那么可以向实数Real字段赋值然后以整数Integer字段读出其前32位(简单地说,作用就是请求整数参量)。
 
接受答案了.
 
后退
顶部