• Delphi 动态数组、静态数组、TBytes 的区别


    结论:

    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;
  • 相关阅读:
    操作系统复习目录
    leetcode Trapping Rain Water
    leetcode First Missing Positive
    leetcode Combination Sum II
    leetcode Word Search 待解决?
    [HDU] 1074 Doing Homework (NP性质的DP,远没有过去的自己写得好了)
    [HDU] 4513 吉哥系列故事——完美队形II
    [HDU] 4512 吉哥系列故事——完美队形I(有点dp味道的递归模拟)
    [HDU] 4519 郑厂长系列故事——体检
    [HDU] 4527 小明系列故事——玩转十滴水
  • 原文地址:https://www.cnblogs.com/CipherLab/p/13324324.html
Copyright © 2020-2023  润新知