Delphi 動態陣列、靜態陣列、TBytes 的區別
阿新 • • 發佈:2020-07-16
結論:
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)-1do 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;