Delphi数组详解

//1. 标准方法: var MyArr: array[0..10] of Integer; //定义静态数组

 //2. 可以使用非0下标: var MyArr: array[9..10] of Integer; //不能提倡,这样不容易与系统函数沟通

 //3. 根据预定义类型来声明数组: type TMyArr = array[0..10] of Integer; //先定义一个数组类型 var MyArr: TMyArr; //再定义静态数组

 //4. 在非过程区可以直接赋值: var MyArr: array[0..2] of Integer = (11,22,33);

 //5. 多维数组: var MyArr: array[0..2, 0..2] of Integer; begin //使用 MyArr[1,2] := 100; end;

 //6. 根据子界定义数组: type TRange = 0..10; var MyArr: array[TRange] of Integer;

 //7. 根据枚举定义数组: type TEnums = (Enum1,Enum2,Enum3); var MyArr: array[TEnums] of string; begin MyArr[Enum1] := '万一'; ShowMessage(MyArr[Enum1]); //万一 end;

 //8. 根据其他类型定义数组: var MyArr: array[Byte] of Char; begin MyArr[255] := #65; ShowMessage(MyArr[255]); //A end; //应尽量不使用内建类型,可以新建类型: type TNewByte = Byte; var MyArr: array[TNewByte] of Char; begin MyArr[255] := #65; ShowMessage(MyArr[255]); //A end; //也可以使用类型别名: type TChar = type Char; var MyArr: array[TChar] of Byte; begin MyArr['C'] := 255; ShowMessage(IntToStr(MyArr['C'])); //255 end; //同时定义类型: type MyRec = record s: string; r: Real; b: Byte; end; var Arr1: array[0..100] of MyRec; Arr2: array[0..100] of record s: string; r: Real; b: Byte; end; //可以直接这样定义 Arr3: packed array[0..100] of MyRec; //压缩数组定义, 好像没有区别?

 


 

 

//例1: var StrArr: array of String; //动态数组定义时不与维数 begin SetLength(StrArr,6); //分配6个元素位置: 0-5 StrArr[0] := '万一'; //动态数组的下界是 0 ShowMessage(StrArr[0]); //分配空间后和静态数组一样使用 StrArr := nil; //一般没必要手动释放, 动态数组离开作用域会自释放 end;

 //例2. 动态数组的引用: var Arr1,Arr2: array of Integer; a: array[0..1] of Integer; begin SetLength(Arr1,6); Arr1[5] := 100; Arr2 := Arr1; //Arr2 引用了 Arr1 ShowMessage(IntToStr(Arr2[5])); //100 ShowMessage(IntToStr(Length(Arr2))); //当然 Arr2 维数也会是 6 ShowMessage(IntToStr(SizeOf(Arr1))); //4, 其实动态数组是个指针 ShowMessage(IntToStr(SizeOf(Arr2))); //4 Arr2[5] := 99; //现在它们指向同一个数组, 改变这个就是改变那个 ShowMessage(IntToStr(Arr1[5])); //99 Arr1 := nil; //释放其中一个指针, 数组继续存在 ShowMessage(IntToStr(Arr2[5])); //99 end;

 //例3. 数组 Copy <1>: var Arr1,Arr2: array of Integer; begin SetLength(Arr1,6); Arr1[5] := 100; Arr2 := Copy(Arr1); //数组 Copy Arr2[5] := 99; //改变 Arr2 不再影响 Arr1 ShowMessage(IntToStr(Arr1[5]-Arr2[5])); //1 SetLength(Arr1,7); ShowMessage(IntToStr(Length(Arr1))); //7 ShowMessage(IntToStr(Length(Arr2))); //6, 没有一点牵扯了 end;

 //例4. 数组 Copy <2>: var Arr1,Arr2: array of Integer; i: Integer; begin SetLength(Arr1,6); for i := Low(Arr1) to High(Arr1) do //给每个元素赋值 Arr1[i] := i+1; Arr2 := Copy(Arr1,1,3); //只 Copy 第2..4个元素 ShowMessage(IntToStr(Arr1[1])); //2, 现在 Arr2[0] 和 Arr1[1] 的值是一样的 ShowMessage(IntToStr(Arr2[0])); //2 ShowMessage(IntToStr(Length(Arr1))); //6, 维数肯定不一样了 ShowMessage(IntToStr(Length(Arr2))); //3 end;

 //例5. 动态多维数组: var Arr: array of array of Integer; //定义多维数组 begin SetLength(Arr,5,5); //分配空间 Arr[0,3] := 100; //赋值 ShowMessage(IntToStr(Arr[0,3])); //取值 end;

 //例6. 另类建立: var Arr: array of Integer; begin Arr := varArrayCreate([0,3],varInteger); ShowMessage(IntToStr(Length(Arr))); //4 Arr := VarArrayOf([1,2,3,4]); ShowMessage(IntToStr(Arr[0])); //1 {这是给变体数组使用的,可能会有效率问题} end;
var Arr: array[0..3] of Variant; begin Arr[0] := 123; Arr[1] := 'wy'; Arr[2] := True; Arr[3] := VarArrayOf([1,'wanyi',1.5]); //变体数组的元素也可以是变体数组 ShowMessage(Arr[0]); //123, 不需要转换 ShowMessage(Arr[1]); //wy ShowMessage(Arr[2]); //True ShowMessage(Arr[3][1]); //wanyi end;
type TMyEnum = (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday); {定义枚举} var weekArr: array[TMyEnum] of string; {定义数组} myEnum: TMyEnum; {定义枚举变量} begin {数组赋值} weekArr[Monday] := '星期一'; weekArr[Tuesday] := '星期二'; weekArr[Wednesday] := '星期三'; weekArr[Thursday] := '星期四'; weekArr[Friday] := '星期五'; weekArr[Saturday] := '星期六'; weekArr[Sunday] := '星期天'; {调用数组} ShowMessage(weekArr[Sunday]); {星期天} {遍历数组} for myEnum := Low(weekArr) to High(weekArr) do begin ShowMessage(weekArr[myEnum]); {将分别显示: 星期一 ... 星期天} end; end; 

 

type TABC = 'A'..'G'; {定义子界} var abcArr: array[TABC] of Integer; {定义数组} abc: TABC; {定义子界变量} begin {数组赋值} abcArr['A'] := 11; abcArr['B'] := 22; abcArr['C'] := 33; abcArr['D'] := 44; abcArr['E'] := 55; abcArr['F'] := 66; abcArr['G'] := 77; {调用数组} ShowMessage(IntToStr(abcArr['G'])); {77} {遍历数组} for abc := Low(abcArr) to High(abcArr) do begin ShowMessage(IntToStr(abcArr[abc])); {11 22 33 44 55 66 77} end; end;
//动态数组一般是不需要手动释放的, 如果需要... var arr: array of Integer; begin {设置动态数组维数} SetLength(arr,10); {释放方法一} arr := nil; {释放方法二} SetLength(arr, 0); {释放方法三} Finalize(arr); end;
//这是常规思路: const arr: array[0..1] of Char = ('A','B'); begin ShowMessage(arr); {AB} ShowMessage(IntToStr(Length(arr))); {2} end;

 //没想到可以这样: const arr: array[Boolean] of Char = ('A','B'); begin ShowMessage(arr); {AB} ShowMessage(IntToStr(Length(arr))); {2} {访问元素} ShowMessage(arr[False]); {A} ShowMessage(arr[True]); {B} {也可以这样访问} ShowMessage(arr[Low(arr)]); {A} ShowMessage(arr[High(arr)]); {B} {但不能这样访问} // ShowMessage(arr[0]); // ShowMessage(arr[1]); {但可以变通一下} ShowMessage(arr[Boolean(0)]); {A} ShowMessage(arr[Boolean(1)]); {B} end;

 //同理, 这样也可以: const arr: array[Byte] of Integer = ( 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81, 82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105, 106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145, 146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165, 166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185, 186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, 206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245, 246,247,248,249,250,251,252,253,254,255,256); begin ShowMessage(IntToStr(arr[Low(arr)])); {1} ShowMessage(IntToStr(arr[High(arr)])); {256} ShowMessage(IntToStr(Length(arr))); {256} end;

 //给这种用法来一个必要性的实例: const BoolStr: array[Boolean] of string = ('False', 'True'); var b: Boolean; begin b := True; ShowMessage(BoolStr[b]); {True} b := not b; ShowMessage(BoolStr[b]); {False} end;
我来提醒大家 
数组定义时,如果唯数是以枚举开始的话,编译指令是从Low()..High() 
所以带有负数值的枚举用来定义数组常量会出错. 
如: 
Type 
TErrorCode = (ecNOERROR = 0, 
ecDisConnect = -1, 
ecOtherError = -2); 
Const 
ErrorLabels : array [TErrorCode] of String =( 
'无错误' , '断开连接' , '其他错误'); 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
Caption := ErrorLabels[ecOtherError]; 
end; 

Caption得到的是:无错误,那是因为Low(TErrorCode)=ecOtherError 
High(TErrorCode)就是ecNOERROR 
//给一个整型开放数组求和的函数 function MyFun(const arr: array of Integer): Integer; var i: Integer; begin Result := 0; for i in arr do Result := Result + i; end; {测试1:} procedure TForm1.Button1Click(Sender: TObject); var num: Integer; begin num := MyFun([1,2,3]); ShowMessage(IntToStr(num)); {6} end; {测试2:} procedure TForm1.Button2Click(Sender: TObject); var iArr: array of Integer; i,x: Integer; begin SetLength(iArr, 10); for i := Low(iArr) to High(iArr) do begin iArr[i] := i + 1; end; x := MyFun(iArr); ShowMessage(IntToStr(x)); {55} end; 

 

之前应该参考一下: 关于开放数组参数


 

//这是在 System 单元定义的一组标识数据类型的常量: vtInteger = 0; vtBoolean = 1; vtChar = 2; vtExtended = 3; vtString = 4; vtPointer = 5; vtPChar = 6; vtObject = 7; vtClass = 8; vtWideChar = 9; vtPWideChar = 10; vtAnsiString = 11; vtCurrency = 12; vtVariant = 13; vtInterface = 14; vtWideString = 15; vtInt64 = 16; //这是定义在 System 单元关于数据类型的一个结构: TVarRec = record case Byte of vtInteger: (VInteger: Integer; VType: Byte); vtBoolean: (VBoolean: Boolean); vtChar: (VChar: Char); vtExtended: (VExtended: PExtended); vtString: (VString: PShortString); vtPointer: (VPointer: Pointer); vtPChar: (VPChar: PChar); vtObject: (VObject: TObject); vtClass: (VClass: TClass); vtWideChar: (VWideChar: WideChar); vtPWideChar: (VPWideChar: PWideChar); vtAnsiString: (VAnsiString: Pointer); vtCurrency: (VCurrency: PCurrency); vtVariant: (VVariant: PVariant); vtInterface: (VInterface: Pointer); vtWideString: (VWideString: Pointer); vtInt64: (VInt64: PInt64); end;

作为参数的开放数组, 有时数组的成员类型是不确定的, 此时应该使用 array of const 定义; 详细举例:


unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} {把不同数据类型返回字符串的函数} function Fun1(arr: array of const): string; var i: Integer; begin Result := ''; for i := Low(arr) to High(arr) do begin case arr[i].VType of vtInteger : Result := Result + IntToStr(arr[i].VInteger) + ' '; vtBoolean : Result := Result + BoolToStr(arr[i].VBoolean, True) + ' '; vtChar : Result := Result + arr[i].VChar + ' '; vtExtended : Result := Result + FloatToStr(arr[i].VExtended^) + ' '; vtString : Result := Result + PShortString(arr[i].VString)^ + ' '; vtPointer : Result := Result + IntToStr(Integer(arr[i].VPointer)) + ' '; vtPChar : Result := Result + arr[i].VPChar + ' '; vtObject : Result := Result + arr[i].VObject.ClassName + ' '; vtClass : Result := Result + arr[i].VClass.ClassName + ' '; vtWideChar : Result := Result + arr[i].VWideChar + ' '; vtPWideChar : Result := Result + arr[i].VPWideChar + ' '; vtAnsiString: Result := Result + PAnsiChar(arr[i].VAnsiString)^ + ' '; vtCurrency : Result := Result + CurrToStr(arr[i].VCurrency^) + ' '; vtVariant : Result := Result + string(arr[i].VVariant^) + ' '; vtInterface : Result := Result + IntToStr(Integer(arr[i].VInterface)) + ' '; vtWideString: Result := Result + PWideChar(arr[i].VWideString) + ' '; vtInt64 : Result := Result + IntToStr(arr[i].VInt64^) + ' '; end; end; end; {简化上一个函数} function Fun2(const arr: array of const): string; var i: Integer; const n = #32; begin Result := ''; for i := Low(arr) to High(arr) do with arr[i] do begin case VType of 0 : Result := Result + IntToStr(VInteger) + n; 1 : Result := Result + BoolToStr(VBoolean, True) + n; 2 : Result := Result + VChar + n; 3 : Result := Result + FloatToStr(VExtended^) + n; 4 : Result := Result + PShortString(VString)^ + n; 5 : Result := Result + IntToStr(Integer(VPointer)) + n; 6 : Result := Result + VPChar + n; 7 : Result := Result + VObject.ClassName + n; 8 : Result := Result + VClass.ClassName + n; 9 : Result := Result + VWideChar + n; 10: Result := Result + VPWideChar + n; 11: Result := Result + PAnsiChar(VAnsiString)^ + n; 12: Result := Result + CurrToStr(VCurrency^) + n; 13: Result := Result + string(VVariant^) + n; 14: Result := Result + IntToStr(Integer(VInterface)) + n; 15: Result := Result + PWideChar(VWideString) + n; 16: Result := Result + IntToStr(VInt64^) + n; end; end; end; {获取类型名的函数} function Fun3(const arr: array of const): string; var i: Integer; const n = sLineBreak; begin Result := ''; for i := Low(arr) to High(arr) do with arr[i] do begin case VType of 0 : Result := Result + 'Integer' + n; 1 : Result := Result + 'Boolean' + n; 2 : Result := Result + 'Char' + n; 3 : Result := Result + 'Extended' + n; 4 : Result := Result + 'String' + n; 5 : Result := Result + 'Pointer' + n; 6 : Result := Result + 'PChar' + n; 7 : Result := Result + 'Object' + n; 8 : Result := Result + 'Class' + n; 9 : Result := Result + 'WideChar' + n; 10: Result := Result + 'PWideChar' + n; 11: Result := Result + 'AnsiString'+ n; 12: Result := Result + 'Currency' + n; 13: Result := Result + 'Variant' + n; 14: Result := Result + 'Interface' + n; 15: Result := Result + 'WideString'+ n; 16: Result := Result + 'Int64' + n; end; end; end; {测试} procedure TForm1.Button1Click(Sender: TObject); var a: Integer; b: Boolean; c: Char; d: Extended; e: ShortString; f: Pointer; g: PChar; h: TButton; i: TClass; j: WideChar; k: PWideChar; l: AnsiString; m: Currency; n: Variant; o: IInterface; p: WideString; q: Int64; begin a := 1; b := True; c := 'a'; d := 2; e := 'S'; f := Pointer(3); g := 'P'; h := TButton(Sender); i := TForm; j := #19975; k := '一'; l := 'A'; m := 4; n := 5; //o; p := '万一'; q := 7; ShowMessage(Fun1([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q])); ShowMessage(Fun2([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q])); {结果如下:} {1 True a 2 S 3 P TButton TForm 万 一 A 4 5 0 万一 7 } ShowMessage(Fun3([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q])); {结果如下: Integer Boolean Char Extended String Pointer PChar Object Class WideChar PWideChar AnsiString Currency Variant Interface WideString Int64 } end; {我试试没有在 TVarRec 中的类型是怎么归类的} procedure TForm1.Button2Click(Sender: TObject); var a: Byte; b: Word; c: Cardinal; d: Double; e: Real; f: TStrings; begin ShowMessage(Fun3([a,b,c,d,e,f])); {结果如下: Integer Integer Integer Extended Extended Object } end; end.

从这个例子中还能得到的启示是(根据网友的提示, 下面可能理解错了!):


//不超过 4 字节的简单类型, 在内存中只有一个存放处. Integer; Boolean; Char; WideChar; //超过 4 字节的类型(包括字符串), 在内存中有两个存放处: 一个是指针位置; 一个是数据位置. Int64; //俺在D7中内存就一个数据位置 Extended; Currency; Variant; ShortString; AnsiString; WideString; //指针: 只有 4 字节大小. Pointer; PChar(PAnsiChar); PWideChar; //对象: 复杂了... Object Class; IInterface;

 

最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适!

如果是一维数组、且元素大小是一个字节, 这样用看不出错误, 譬如:


var arr1: array[0..9] of Char; arr2: array[0..9] of Byte; begin ShowMessageFmt('%d,%d,%d,%d',[Length(arr1), SizeOf(arr1), Length(arr2), SizeOf(arr2)]); {显示结果: 10,10,10,10} end;

但如果数组元素多于一个字节、或是多维数组的情况下, 就不行了, 举例:


const arr1: array[0..9] of Integer = (1,2,3,4,5,6,7,8,9,10); arr2: array[0..1, 0..3] of Integer = ((1,2,3,4), (5,6,7,8)); var arr3: array[Boolean] of Integer; arr4: array[Byte] of Integer; begin ShowMessage(IntToStr(Length(arr1))); {10} ShowMessage(IntToStr(SizeOf(arr1))); {40} ShowMessage(IntToStr(Length(arr2))); {2} ShowMessage(IntToStr(Length(arr2[0]))); {4} ShowMessage(IntToStr(Length(arr2[1]))); {4} ShowMessage(IntToStr(SizeOf(arr2))); {32} ShowMessage(IntToStr(Length(arr3))); {2} ShowMessage(IntToStr(SizeOf(arr3))); {8} ShowMessage(IntToStr(Length(arr4))); {256} ShowMessage(IntToStr(SizeOf(arr4))); {1024} end;

我们倒是可以利用这个原理, 迅速知道多维数组的元素总数:


const arr: array[0..1, 0..2, 0..3] of Integer = (((1,1,1,1), (2,2,2,2), (3,3,3,3)), ((4,4,4,4), (5,5,5,5), (6,6,6,6))); begin ShowMessage(IntToStr(SizeOf(arr) div SizeOf(Integer))); {24} end;
如何把字符串覆给数组

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} {把字符串给静态(字符)数组} procedure TForm1.Button1Click(Sender: TObject); const str = '万一的 Delphi 博客'; var StaticArr: array[0..255] of Char; begin {直接赋值即可} StaticArr := str; {显示} ShowMessage(StaticArr); {万一的 Delphi 博客} end; {把字符串给动态(字符)数组} procedure TForm1.Button2Click(Sender: TObject); const str = '万一的 Delphi 博客'; var DynamicArr: array of Char; i: Integer; begin {设置动态数组大小} SetLength(DynamicArr, Length(str)); {把字符串赋给动态数组} for i := 0 to Length(DynamicArr) - 1 do DynamicArr[i] := str[i+1]; {显示动态数组中的字符} ShowMessage(PChar(@DynamicArr[0])); {万一的 Delphi 博客} end; {数组元素可不一定都是字符} procedure TForm1.Button3Click(Sender: TObject); const str = '万一的 Delphi 博客'; var DynamicArr: array of string; begin SetLength(DynamicArr, 1); DynamicArr[0] := str; ShowMessage(DynamicArr[0]); {万一的 Delphi 博客} end; end. 


本例效果图:


unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Button2: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Align := alLeft; end; {多维动态数组} procedure TForm1.Button1Click(Sender: TObject); var Arr: array of array of array of Integer; {定义一个三维动态数组} i,j,k,ic,jc,kc: Integer; begin {设置数组} SetLength(Arr, 2,3,4); {获取各维的维数} ic := Length(Arr); jc := Length(Arr[0]); kc := Length(Arr[0][0]); {赋值} for i := 0 to ic - 1 do for j := 0 to jc - 1 do for k := 0 to kc - 1 do Arr[i][j][k] := Random(100); {取值} Memo1.Clear; for i := 0 to ic - 1 do for j := 0 to jc - 1 do for k := 0 to kc - 1 do Memo1.Lines.Add(Format('Arr[%d][%d][%d] = %d', [i, j, k, Arr[i][j][k]])); end; {多维动态数组指针} procedure TForm1.Button2Click(Sender: TObject); Type TMyArr = array of array of array of Integer; {定义一个三维动态数组类型} var PArr: ^TMyArr; {动态数组指针变量} i,j,k,ic,jc,kc: Integer; begin {用作维数的变量} ic := 2; jc := 3; kc := 4; {分配内存; 按说动态数组还需要 8 个管理字节, 我不知道 Delphi 是怎么协调的} GetMem(PArr, ic * jc * kc * SizeOf(Integer)); {设置数组} SetLength(PArr^, ic,jc,kc); {赋值} for i := 0 to ic - 1 do for j := 0 to jc - 1 do for k := 0 to kc - 1 do PArr^[i][j][k] := Random(100); {取值} Memo1.Clear; for i := 0 to ic - 1 do for j := 0 to jc - 1 do for k := 0 to kc - 1 do Memo1.Lines.Add(Format('Arr[%d][%d][%d] = %d', [i, j, k, PArr^[i][j][k]])); {自己分配的内存要负责释放} FreeMem(PArr); end; end. 


本例通过存取结构, 慢慢引入了数组类型与指针的一些使用方法; 其中六个小例子的测试内容和结果都是一样的.


unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} type {先定义结构和结构指针} PMyRec = ^TMyRec; TMyRec = record F1: Char; F2: Word; end; {用静态数组储存或读写结构很方便} procedure TForm1.Button1Click(Sender: TObject); var ArrRec: array[0..2] of TMyRec; i: Integer; begin {写入} for i := 0 to 2 do begin ArrRec[i].F1 := Chr(i+65); ArrRec[i].F2 := (i+1) * 10; end; {读取} for i := 0 to Length(ArrRec) - 1 do ShowMessageFmt('%s, %d', [ArrRec[i].F1, ArrRec[i].F2]); end; {这个只是定义了一块内存, 没用数组的概念, 有点麻烦} procedure TForm1.Button2Click(Sender: TObject); var buf: PMyRec; begin GetMem(buf, SizeOf(TMyRec) * 3); {申请内存} {写入} buf^.F1 := 'A'; buf^.F2 := 10; Inc(buf); {到下一个} buf^.F1 := 'B'; buf^.F2 := 20; Inc(buf); buf^.F1 := 'C'; buf^.F2 := 30; Dec(buf, 2); {回到开始} {读取} ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]); Inc(buf); {到下一个} ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]); Inc(buf); ShowMessageFmt('%s, %d', [buf^.F1, buf^.F2]); Dec(buf, 2); {回到开始} FreeMem(buf); {释放内存} end; {可以给结构定义一个数组类型} procedure TForm1.Button3Click(Sender: TObject); type TArr = array of TMyRec; var buf: PMyRec; i: Integer; begin GetMem(buf, SizeOf(TMyRec) * 3); for i := 0 to 2 do begin TArr(buf)[i].F1 := Chr(i+65); TArr(buf)[i].F2 := (i+1) * 10; end; for i := 0 to 2 do ShowMessageFmt('%s, %d', [TArr(buf)[i].F1, TArr(buf)[i].F2]); FreeMem(buf); end; {直接用动态数组也行} procedure TForm1.Button4Click(Sender: TObject); var Arr: array of TMyRec; i: Integer; begin SetLength(Arr, 3); for i := 0 to 2 do begin Arr[i].F1 := Chr(i+65); Arr[i].F2 := (i+1) * 10; end; for i := 0 to 2 do ShowMessageFmt('%s, %d', [Arr[i].F1, Arr[i].F2]); end; {使用一个元素的数组指针, 这是很常用的} procedure TForm1.Button5Click(Sender: TObject); type PArr = ^TArr; TArr = array[0..0] of TMyRec; var buf: PArr; i: Integer; begin GetMem(buf, SizeOf(TMyRec) * 3); for i := 0 to 2 do begin buf^[i].F1 := Chr(i+65); buf^[i].F2 := (i+1) * 10; end; {用这种方法不能像下面这样读写, 也就是 [] 中不能是超过 0 的常数, 但可以用变量} {这也容易理解, 因为常量会直接编译到代码中, 在没有分配内存以前, 编译器不知道数组会更大} {要解决这个问题需要用下一个方法} // buf[0].F1 := 'A'; // buf[0].F2 := 10; // buf[1].F1 := 'B'; // buf[1].F2 := 20; // buf[2].F1 := 'C'; // buf[2].F2 := 30; for i := 0 to 2 do ShowMessageFmt('%s, %d', [buf[i].F1, buf[i].F2]); FreeMem(buf); end; {使用一个超大的数组指针, Delphi 的 TList 类就是这么干的} procedure TForm1.Button6Click(Sender: TObject); type PArr = ^TArr; TArr = array[0..100000] of TMyRec; {不要担心内存暴涨, 使用时我们只用其指针} var buf: PArr; i: Integer; begin GetMem(buf, SizeOf(TMyRec) * 3); for i := 0 to 2 do begin buf^[i].F1 := Chr(i+65); buf^[i].F2 := (i+1) * 10; end; {和上例不同的是, 下面的代码也可以} // buf[0].F1 := 'A'; // buf[0].F2 := 10; // buf[1].F1 := 'B'; // buf[1].F2 := 20; // buf[2].F1 := 'C'; // buf[2].F2 := 30; for i := 0 to 2 do ShowMessageFmt('%s, %d', [buf[i].F1, buf[i].F2]); FreeMem(buf); end; end.


unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} type TArr = array of Int64; {先把需要的动态数组数组定义成一个类型, 因为下面需要类型转换} var arr1,arr2: TArr; {两个等待测试的数组变量} p: Pointer; {该指针用于中转数组中的数据} {先给第一个数组赋测试值} procedure TForm1.FormCreate(Sender: TObject); var i: Integer; begin for i := 0 to 1000 - 1 do begin SetLength(arr1, Length(arr1)+1); arr1[High(arr1)] := i * 2; end; {抽查显示} ShowMessage(IntToStr(arr1[9])); {18} end; {复制到第二个数组} procedure TForm1.Button1Click(Sender: TObject); var size: Cardinal; begin size := Length(arr1) * SizeOf(arr1[0]); {源数组大小} GetMem(p, size); {根据源数组大小分配内存} CopyMemory(p, arr1, size); {复制} arr2 := TArr(p); {转换} {抽查显示} ShowMessage(IntToStr(arr2[9])); {18} end; end.


假定数组元素是个结构, 再测试一次:


unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} type TRec = record str: string; int: Integer; end; TArr = array of TRec; var arr1,arr2: TArr; p: Pointer; procedure TForm1.FormCreate(Sender: TObject); var i: Integer; begin for i := 0 to 1000 - 1 do begin SetLength(arr1, Length(arr1)+1); arr1[High(arr1)].str := IntToStr(i); arr1[High(arr1)].int := i * 2; end; ShowMessageFmt('%s,%d',[arr1[9].str, arr1[9].int]); {9,18} end; procedure TForm1.Button1Click(Sender: TObject); var size: Cardinal; begin size := Length(arr1) * SizeOf(arr1[0]); GetMem(p, size); CopyMemory(p, arr1, size); arr2 := TArr(p); ShowMessageFmt('%s,%d',[arr2[9].str, arr2[9].int]); {9,18} end; end. 
posted @ 2011-10-28 13:27  ahroot  阅读(4887)  评论(1编辑  收藏  举报