动态数组介绍----Delphi

原创 2002年09月05日 15:18:00

动态数组介绍----Delphi<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

自从有了动态数组,链表除了在教科书里出现外,已经很少在实际编程中被使用了,事实也是如此,数组的确比传统链表快得多,而且也方便的多。

    从 Delphi4起,开始了内建各种类型的动态数组支持。但是,对我们来说动态数组支持似乎做的不够彻底,因为Delphi竟然连删除、插入、移动连续元素的函数都没有提供,让人使用起来总觉得不够爽!!! J 。作为一名程序员,我们当然要有自己解决问题的能力,下面就让我们简单介绍一下Delphi 下的动态数组。

Delphi中,数组类型有静态数组(a : array[0..1024] of integer)、动态数组(var a : array of integer)、指针数组(即指向静态数组的指针)和开放数组(仅用于参数传递)。静态数组、指针数组有速度快的好处,动态数组有大小可变的优势,权衡之下就有了折衷的办法,那就是定义的动态数组在必要时转换为指针。

动态数组声明之后,只有下面几个函数可供操作:

1.  设置数组大小,可以任意缩减或增加数组大小

Procedure SetLength(var S ; NewLength : integer);

2.  取出连续元素,复制给另一个数组变量

Function Copy(s;Index,Count : integer) : array ;

3.  取得数组大小及上下限

Function Length(s):integer;

Function High(x):integer;

Function Low(x):integer;

值得注意的是,不加const或var修饰的动态数组会被作为形参传递,而动态数组用const修饰并不意味着你不能修改数组里的元素(不信你可以字自己在程序中试试。还有一点是High函数调用了Length 函数,所以我们在获取数组上限时最好直接用 Length(s) 函数。

动态数组在内存空间中占用4个字节.   动态数组在内存中的分配表如下:

偏移量                                      内容

-8                                   32-bit 引用计数

-4                                   32-bit 数组长度

0..数组长度 * (元素尺寸) - 1   数组元素    元素尺寸=Sizeof(元素类型)

根据上面的分配情况,可以得到如下结果:

如果我们想要清空一个动态数组只需要把“数组长度”和“引用计数”清空即可。”引用上面的一句话就是:“权衡之下就有了折衷的办法,那就是定义的动态数组在必要时转换为指针。”下面是清空动态数组的函数:

procedure DynArraySetZero(var A);

var

  P: PLongint; //占用4个字节,正好符合 32 位内存排列

begin

  P := PLongint(A); // 指向 A 的地址

  Dec(P); //P 地址偏移量是 sizeof(A),指向了数组长度

  P^ := 0; // 长度清空

  Dec(P); // 指向引用计数

  P^ := 0; //计数清空。

end;

上面的函数就这么简单,而且效率也非常高。

下面让我们再来看看怎样删除动态数组中的元素,函数体如下:

{************************************

 A 变量类型  , elSize = SizeOf(A)

index 开始删除的位置索引 ,Count 删除的数量

****************************************}

procedure DynArrayDelete(var A; elSize: Longint; index, Count: Integer);

var

  len, MaxDelete: Integer;

  P : PLongint; //4 个字节的长整形指针

begin

  P := PLongint(A);// 取的 A 的地址

  if P = nil then

    Exit;

  {

下面这句完全等同于 Dec(P) ; len := P^  因为 Dec(P) = Pchar(P) – 4  同样是移动4 字节的偏移量,只不过后者按字节来移动    }

len := PLongint(PChar(P) - 4)^; // 变量的长度 ,偏移量 -4

  if index >= len then //要删除的位置超出范围,退出

    Exit;

  MaxDelete := len - index; // 最多删除的数量

  Count := Min(Count, MaxDelete); // 取得一个较小值

  if Count = 0 then // 不要求删除

    Exit; 

Dec(len, Count);// 移动到要删除的位置

  MoveMemory(PChar(P)+index*elSize , PChar(P)+(index + Count)*elSize , (len-index)*elSize); //移动内存

  Dec(P);  //移出 “数组长度”位置

  Dec(P);  //移出“引用计数” 位置

  //重新再分配调整内存,len 新的长度. Sizeof(Longint) * 2 = 2*Dec(P)

  ReallocMem(P, len * elSize + Sizeof(Longint) * 2);

  Inc(P); // 指向数组长度

  P^ := len; // new length

  Inc(P); // 指向数组元素,开始的位置

  PLongint(A) := P;

end;

 

对上面的例子,我们需要注意的是 elSize 参数 ,它必须是 SizeOf(DyArray_Name),表示元素所占用的字节数。

    相信看了上面的例子后,对于动态数组的拷贝,移动想必也可以自己实现了吧 J

后续:

    其实,Delphi 对许多类型的内存分配都很相似,比如 string 类型,其实它和动态数组是很相似的,我们完全可以把它拿来当成动态数组。实质上 string 是 Pchar 的简易版本。不管怎么说,了解一些内存的分配对我们这些开发人员来说还是有一些好处的。

delphi 动态数组的使用

动态数组的使用 //例1: var StrArr: array of String; //动态数组定义时不与维数 begin SetLength(StrArr,6); //分配6个元素位置:...
  • piaoxiangjianyu110
  • piaoxiangjianyu110
  • 2013年01月20日 19:06
  • 769

Delphi多维动态数组重定义长度

Delphi在定义多维数组时有两种方法:动态定义或静态定义 动态定义:bufanalog0:array of array of array of array of byte; 在使用前重设长度:  i...
  • c_huabo
  • c_huabo
  • 2010年07月15日 15:34
  • 3807

给动态数组一次性赋值

给动态数组一次性赋值
  • baronyang
  • baronyang
  • 2010年06月06日 20:45
  • 3158

Delphi中将文件流的数据写入动态数组

varmyfile:TfileStream;mybuf:array of Pchar;beginmyfile:=TfileStream.Create(d:/a.txt,fmOpenReadWrite)...
  • itsoft2006
  • itsoft2006
  • 2007年03月15日 22:53
  • 2132

delphi中为动态数组分配空间的问题

在delphi中为动态数组分配空间应该使用SetLength函数,释放空间也使用Setlength,只不过长度应该为0。今天发现一段代码是用GetMem来为动态数组分配空间的,用FreeMem来释放空...
  • webouse
  • webouse
  • 2008年12月02日 17:31
  • 2122

Delphi7 动态数组

初学Delphi,感觉.......这感觉就是写代码太费劲了,已经习惯了c#那种信手拈来,不能说pascal不适应只能说还是费劲,可能是D7太老了,也可能是我还没有上道儿,就这么着吧,下面简单的写俩函...
  • u013402605
  • u013402605
  • 2015年06月14日 22:14
  • 330

Delphi动态数组介绍

从 Delphi4起,开始了内建各种类型的动态数组支持。但是,对我们来说动态数组支持似乎做的不够彻底,因为Delphi竟然连删除、插入、移动连续元素的函数都没有提供,让人使用起来总觉得不够爽!!! J...
  • chenyq2008
  • chenyq2008
  • 2008年09月27日 11:40
  • 8432

delphi 初始化多维动态数组的方法

procedure TForm1.Button1Click(Sender: TObject);      var a:array of array of double; begin     se...
  • stbaby
  • stbaby
  • 2011年09月29日 15:32
  • 1573

delphi 动态数组和静态数组首地址的区别

动态数组开始地址和静态数组的开始地址是不同的,注意下面代码中的File.Read函数的第一个参数动态数组使用var Source : array of byte;  File : TFileStrea...
  • webouse
  • webouse
  • 2008年10月16日 11:01
  • 2800

Delphi泛型动态数组的扩展,归属 武稀松 所有!

武稀松真的是Delphi 界里的一个大银才,他写的博客文章非常新颖和实用,如今竟然将泛型数组封装的如此有声有色。 我对这个泛型动态数组的扩展爱不释手,在他开源的代码上,增加了排序和搜索两个小功能,纯属...
  • rznice
  • rznice
  • 2014年03月18日 19:54
  • 3424
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:动态数组介绍----Delphi
举报原因:
原因补充:

(最多只允许输入30个字)