今天学习的时候,看到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, 256); //shortstring默认开辟256个连续字节
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;