一个关于string分配内存的问题 (100分)

  • 主题发起人 主题发起人 snowrain
  • 开始时间 开始时间
对于 ShortString,是在 str[0] 存放长度的,因为只有 1 个字节,所以字符串
长度只有 255。但是那是 Pascal 时代的事情了。
现在的 Delphi 默认的字符串是 AnsiString,其长度存放在负偏移 4 字节的位置
所以长度可以达到 4G。而一个 AnsiString 的变量其实是一个指针,即 4 个字节
比如:
var
str: string; // AnsiString,即编译器选项的 HugeString
begin
str := 'Hello';
假如这时 str 中存放的是 1234H, 那么实际的字符 'H' 是存放在地址 1234H 处的
而 1234H 的负 4 字节偏移处,即 1230H 处存放的就是 str 的长度:5
Length 函数就是直接读取这个数值,所以比要从头到尾扫描字符串结束符的 strlen
快得多。
刚才说了,声明 str: string 是声明的一个 AnsiString;那么 str1: string[20]呢?
它是一个 ShortString,因为你指明了长度,对他,你不必再动态分配空间

所以,伊天仇 的说法的确是错误的,指针的长度的确是定长。但是 Length(s) 取得的
并不是指针 s 的长度,它取的什么,我已经讲过了。 我知道你的试验的意思,不过
你要做这个试验的话,应该将 Length(s) 换成 SizeOf(s),那你就会知道结果了:)

现在回答 snowrain 最开始提出的问题:

RTest=Record
Name:string[20]; // 长度 20+1; 由于 字段对齐,增至 24
Identifier:integer; // 4;
Content:string; // 4;
end;
所以 SizeOf(RTest) = 24 + 4 + 4 = 32,因此 New(p) 也是分配那么多内存
 
多谢aizb和beat的详尽解析,本人已从中受启!另外:
RTest=Record
Name:string[20]; // 长度 20+1; 由于 字段对齐,增至 24
Identifier:integer; // 4;
Content:string; // 4;
end;
中的“由于 字段对齐,增至 24”是什么意思?? 为何要这样做呢?

 
系统分配内存时都是分配2的n次方,如2、4、8等。如果自定义的内存量和系统分配的不符,
就会产生所谓的“内存碎片”
 
{$A+} 字段对齐
在{$A+}(默认值)的情形下, 如果没有使用 packed 修饰词宣告的 record 型态,其字段会以CPU可以有效存取的方式向 1. 2. 4 等边界对齐, 以获取最佳的存取速度。以下列的程序示例来说:

{$A+}
type
MyRecord = record
ByteField: byte;
IntegerField: integer;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(SizeOf(MyRecord)));
end;

ShowMessage在{$A+}时显示的结果是:「8」; 倘若是{$A-}, 那所得的结果是「5」, 按理说, Byte应该只要一个byte就足够了, 但是考虑到硬件的执行特性, 经过对齐后的record会有比较好的执行速度。

有关这个Compiler Directive要注意的事项是: 不管{$A}的开关是ON或OFF, 使用packed修饰过的记录宣告, 是一定不会对齐的. 例如:

MyRecord = packed record // 不会对齐的记录宣告方式

 
PTest=^RTest;
RTest=Record
Name:string[20];//这里name是个短字符型(21字节)。
Identifier:integer;//4字节长度
Content:string;//这里Content是指针(4字节),
end;
//如果为紧凑型的record(packed record)上面的长度为29字节。
prcedure test;
var
p:PTest;
begin
New(p);//改为New(p,sizeof(p))
p^.Name:='...';
...
end;
--------------------------------------------------
String其实就是一个指针引用,你可以试试:
var str:string;int:integer;
str:='aaaaaaa';
int:=sizeof(str);
得到int为4字节,那么就得到结论:string就是一个指针引用。
我们经常用到string和string[20]两种,他们有什么区别:
var mystr:string[20];申明与下面是一致的
type tempstr=string[20];//这里将为它分配21个字节空间。短字符型
var mystr:tempstr;
明白了吗?
 
to aizb: 哇!高!深!受益非浅!谢了!
 
后退
顶部