1. 动态数组
dArr1: array of byte,数组的名称是一个地址,该地址和数组的第一个元素的地址不一样。该地址的值是第一个元素的地址。
dArr3: TBytes,和array of byte一样,只是一个别名,但是,有些函数的参数类型就是TBytes,你如果传array of byte的参数进去,会发生错误。
2. 静态数组(定义时即指定大小)
dArr2: array[0..9] of byte,数组的名称是一个地址,该地址和数组的第一个元素的地址重合。
3. TMemorySteam
列出内存流的原因是因为,通过内存流读写数组时,非常容易出错。而且,array of byte的参数和TBytes参数会指向不同的函数体,所以需要重点列出。
演示界面:代码
procedure TForm1.Button1Click(Sender: TObject);
var
sArr : array[0..9] of Byte; //静态数组
pB : ^Byte;
i : Integer;
sTmp : string;
begin
Memo1.Lines.Append('');
for i := 0 to 9 do
sArr[i] := ord('a') + i;
sTmp := '';
for i := 0 to Length(sArr)-1 do
sTmp := sTmp + IntToStr(sArr[i]) + ' ';
Memo1.Lines.Append('静态数组的内容');
Memo1.Lines.Append(sTmp);
pB := @sArr;
sTmp := '静态数组的地址:' + IntToStr(Integer(pB));
Memo1.Lines.Append(sTmp);
pB := @(sArr[0]);
sTmp := '静态数组第一个元素的地址:' + IntToStr(Integer(pB));
Memo1.Lines.Append(sTmp);
pB := @sArr;
sTmp := '';
for i := 0 to Length(sArr)-1 do
begin
sTmp := sTmp + IntToStr(pB^) + ' ';
pB := Pointer(LongWord(pB) + 1); //相当于 Inc(pB)
end;
Memo1.Lines.Append('以指针访问静态数组的内容');
Memo1.Lines.Append(sTmp);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
dArr : array of byte; //动态数组
pB : ^Byte;
i : Integer;
sTmp : string;
nValue : Integer;
begin
Memo1.Lines.Append('');
SetLength(dArr, 10);
for i := 0 to Length(dArr)-1 do
dArr[i] := ord('A') + i;
sTmp := '';
for i := 0 to Length(dArr)-1 do
sTmp := sTmp + IntToStr(dArr[i]) + ' ';
Memo1.Lines.Append('动态数组的内容');
Memo1.Lines.Append(sTmp);
pB := @dArr;
sTmp := '动态数组的地址:' + IntToStr(Integer(pB));
Memo1.Lines.Append(sTmp);
//可以看到,动态数据其实是一个地址,这个地址存放的值是数据第一个元素的地址
nValue := (PInteger(pB))^ ;
sTmp := '动态数组地址中的内容:' + IntToStr(nValue);
Memo1.Lines.Append(sTmp);
pB := @(dArr[0]);
sTmp := '动态数组第一个元素的地址:' + IntToStr(Integer(pB));
Memo1.Lines.Append(sTmp);
pB := @(dArr[0]);
sTmp := '';
for i := 0 to Length(dArr)-1 do
begin
sTmp := sTmp + IntToStr(pB^) + ' ';
Inc(pB);
end;
Memo1.Lines.Append('以指针访问动态数组的内容');
Memo1.Lines.Append(sTmp);
end;
procedure TForm1.Button3Click(Sender: TObject);
var
stream : TMemoryStream;
dArr1 : array of Byte; //动态数组
dArr2 : array of Byte;
//TBytes其实就是array of Byte,但是有了新名字,编译器就可找到以TBytes为参数
//类型的重载函数了,这就是重新定义一个名字的意义
//dArr1 : TBytes; //动态数组
//dArr2 : TBytes;
i : integer;
sTmp : string;
offset : Integer;
count : Integer;
begin
Memo1.Lines.Append('');
SetLength(dArr1, 10);
for i := 0 to Length(dArr1)-1 do
dArr1[i] := ord('A') + i;
stream := TMemoryStream.Create;
stream.SetSize(Length(dArr1));
//注意,由于参数是 var类型,所以会取传入变量的地址进行作业,
//所以dArr1[0]是正确的
//而dArr1只是一个地址,这个地址的值才是数组的地址,所以传dArr1是错误的
//w
//stream.Write(dArr1[0], Length(dArr1)); //OK
//stream.Write(dArr1, Length(dArr1)); //NG
//stream.Write(Pointer(dArr1)^, Length(dArr1));//OK
//stream.Write(TBytes(dArr1), Length(dArr1)); //OK
//当参数的动态数组用TBytes转化时,实际执行的是下面这个函数,所以也不会出错
//function TStream.Write(const Buffer: TBytes; Count: Longint): Longint;
//begin
//Result := Write(Buffer, 0, Count);
//end;
//所以,下面这样调用也是OK的
stream.Write(TBytes(dArr1), 0, Length(dArr1)); //OK
SetLength(dArr2, 10);
stream.Position := 0;
stream.Read(dArr2[0], 10); //OK
//stream.Read(Pointer(dArr2)^, 10); //OK
//stream.Read(TBytes(dArr2), 10); //OK
//stream.Read(TBytes(dArr2), 0, 10); //OK
//dArr2被定义成TBytes,OK; 定义为 array of byte, NG
//stream.Read(dArr2, 10);
//stream.Read(dArr2, 0, 10);
sTmp := '';
for i := 0 to Length(dArr1)-1 do
begin
sTmp := sTmp + IntToStr(dArr1[i]) + ' ';
end;
Memo1.Lines.Append('数组1的内容');
Memo1.Lines.Append(sTmp);
sTmp := '';
for i := 0 to Length(dArr2)-1 do
begin
sTmp := sTmp + IntToStr(dArr2[i]) + ' ';
end;
Memo1.Lines.Append('内存流读出的内容');
Memo1.Lines.Append(sTmp);
end;