在windows中内存的分配一次是4个字节的。而packed按字节进行内存的申请和分配,这样速度要慢一些,因为需要额外的时间来进行指针的定位。因此如果不用packed的话,delphi将按一次4个字节的方式申请内存,因此如果一个变量没有4个字节宽的话也要占4个字节!这样就浪费了,你可以用packed关键字取消这种优化。
例子:
type
myrec = packed record
n1 : integer; 4个字节
n2 : shortint; 1个字节
end;
sizeof(myrec)------ 5
type
myrec = record
n1 : integer;
n2 : shortint;
end;
sizeof(myrec)------ 8
Record的数据各个字节都是对齐的,数据格式比较完整,所以这种格式相对packed占用的内存比较大,
但是因为格式比较整齐,所以电脑读取这个类型的数据的时候速度比较快。
而Packed Record对数据进行了压缩,节省了内存空间,当然他的速度也变的慢了。
type
// Declare an unpacked record
TDefaultRecord = Record
name1 : string[4];
floater : single;
name2 : char;
int : Integer;
end;
// Declare a packed record
TPackedRecord = Packed Record
name1 : string[4];
floater : single;
name2 : char;
int : Integer;
end;
var
defaultRec : TDefaultRecord;
packedRec : TPackedRecord;
begin
ShowMessage('Default record size = '+IntToStr(SizeOf(defaultRec)));
ShowMessage('Packed record size = '+IntToStr(SizeOf(packedRec)));
end;
Default record size = 20
Packed record size = 14
不过,对于现在的操作系统来,packed Record 节省的那些空间已不用考虑他了。除了做DLL(不用packed容易造成内存混乱)和做硬件
编程时(比如串口)编程时必须用到packed Record,其它情况都可以用Record
呵呵。 PIPI给我上了一课。 多谢。我犯了形而上学想当然的错误
专门试了一下
procedure TForm1.Button1Click(Sender: TObject);
var a: packed array[1..10] of Integer;
b: array[1..10] of Integer;
begin
a[1] := 1;
a[2] := 256;
a[3] := 65535;
a[4] := 65535;
a[5] := 100000;
Edit1.Text := IntToStr(Sizeof(a));
b[1] := 1;
b[2] := 256;
b[3] := 65535;
b[4] := 65535;
b[5] := 100000;
Edit2.Text := IntToStr(Sizeof(b));
end;
两者是同样的内存尺寸
有 Packed 的占用内存小,但是速度慢一点
没 Packed 的占用内存大,但是速度快一点
比如说,有一个结构t,你又使用了一个a很大的array of t,那么可能要节省一点内存
但是,如果你不是申请很多t的实例,那么不用节省几个byte,要知道现在内存很大了
1M那可是 100多万 byte啊
另外,说一下为什么align了就快:
比如一个integer 4个字节,如果他的气死地址是4的倍数,0、4、8、12……
那么一次时钟(还是总线?)周期就可以读写它,
如果起始于1、2、3,那么要分2个周期才能读写它
用了packed后数据会压缩,但速度变慢。这就是两者的区别!
比如
packed record
aaa:byte
bbb:inetegr
ccc:byte
end //只占用6字节
而
record
aaa:byte
bbb:inetegr
ccc:byte
end //占用12个字节
delphi缺省使用 没有packed 的
Packed 还有一个要考虑的地方就是,如果你要做DLL的话,那么参数的传递就要用Packed的,否则很容易造成内存的写乱.
一般為了效率考量, structure, array.. 之類的資料, complier 會把記億體做所謂 alignment (對齊?) 的調整, 這樣存取時會比較快速
舉個例子, 沒有特別調整 complier 的 alignment 時:
type
TTest = record
x: integer; // 4 bytes
y: char; // 1 byte, 但實際上會是占 4 bytes
end;
你可以做一個簡單的測試, sizeof(TTest) 會等於 8
但如果加上 packed 時, 則 complier 不做 alignment,
這時就會是你真正定義的長度了:
type
TTest = packed record
x: integer; // 4 bytes
y: char; // 1 byte, 實際上也會是占 1 byte
end;
跑出來的結果, sizeof(TTest) 會等於 5
一般是不需 packed, 但如果需要這樣的應用 (如與dll接軌, 硬體控制),
就可能需要拿出來使用..
PS: packed 相當於 {$A1}
s07452你好:
宣告記錄型態(record),預設的編譯方式會將各欄佔用的記憶體長度以方便CPU存取的方式向word或double-word佔用空間大小對齊,以得到較佳的存取速度。如果宣告時使用packed record,則按照實際各欄佔用空間配置,但存取速度較差。你可以參考HELP裡關於packed的說明。