今天學習的時候,看到RTTI結構裏用了蠻多PShortString指針,由於ShortString比較特殊,所以操作PShortString的簡單demo鞏固一下
值得注意的是:
1.平常項目中一般不會使用PShortString,一般直接使用PChar操作內存,也很少在一個結構體中添加變長的成員變量。
//推薦做法,Desc記得要GetMem()/FreeMem()
PMyRecord = ^TMyRecord;
TMyRecord = record
ID : Integer;
Desc : PChar;
end;
2.如果實在需要在結構體中添加變長的成員變量,可以使用變長數組代替(array of Type),請務必要放在最後。
//推薦做法
PMyRecord = ^TMyRecord;
TMyRecord = record
ID : Integer;
Name : array[0..127] of char;
Reserved : array of Integer;
end;
//糟糕的做法
PMyRecord = ^TMyRecord;
TMyRecord = record
ID : Integer;
Reserved : array of Integer; //萬一該不定長數組長度變化了,後面的成員地址全部要挪動
Name : array[0..127] of char;
end;
3.如果結構體中需要不定長的字符串成員,可以使用字符數組代替,數組長度可設大一點,如:array[0…1023] of char。
PMyRecord = ^TMyRecord;
TMyRecord = record
ID : Integer;
Name : array[0..1023] of char; //設置大一點沒關係
Desc : PChar;
end;
4.一般情況下,不會在結構體中定義string類型的成員
//糟糕的做法
TMyRecord = record
...
Name : String;
end
以上的建議可以避免繁瑣的內存管理。
type
PMyRecord = ^TMyRecord;
TMyRecord = record
ID : Integer;
Name : ShortString;
Desc : PShortString;
end;
...
procedure TForm2.btn1Click(Sender: TObject);
var
pMy : PMyRecord;
index : Integer;
tempStr : PShortString;
begin
New(pMy);
index := 0;
FillChar(pMy^, SizeOf(TMyRecord), #0);
GetMem(pMy^.Desc, 1); //只申請一個空間
FillChar(pMy.Desc^, SizeOf(pMy.Desc^), #0);
pMy^.ID := 1;
pMy^.Name := 'test1abcd';
pMy^.Desc^ := 'ggaaddggkkll'; //12個字母
Move(pMy^.ID, FPChar[0], SizeOf(pMy^.ID));
index := index + SizeOf(pMy^.ID);
//shortstring第0位保存了字符串的長度,所以這裏要+1
Move(pMy^.Name, FPChar[index], Length(pMy^.Name) + 1);
index := index + Length(pMy^.Name) + 1;
Move(pMy.Desc^, FPChar[index], Length(pMy^.Desc^) + 1);
//print
index := SizeOf(Integer);
tempStr := PShortString(@FPChar[index]);
ShowMessage(tempStr^);
index := index + Length(pMy^.Name) + 1;
tempStr := PShortString(@FPChar[index]);
ShowMessage(tempStr^);
FreeMem(pMy^.Desc);
Dispose(pMy);
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
GetMem(FPChar, 1000);
FillChar(FPChar^, SizeOf(FPChar^), #0);
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
FreeMem(FPChar);
end;