вопрос указателя delphi - PullRequest
       31

вопрос указателя delphi

3 голосов
/ 19 августа 2011

У меня есть следующий код, который работает, но я не понимаю его на 100% (см. Комментарии из кода):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TMyRec=record
    a:Integer;
    b:String;
  end;
  TRecArray=array of TMyRec;
  PRecArray = ^TRecArray;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
   v1:TRecArray;
   procedure Test(a:PRecArray);
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
 SetLength(v1,3);
 v1[0].b:='test1';//set the first value
 Test(PRecArray(v1));//call method to change the value assigned before
end;

procedure TForm1.Test(a: PRecArray);
begin
 ShowMessage(v1[0].b);//shows test1
 try
  a^[0].b:='test2' //this is raising an error...
 except

 end;
 PRecArray(@a)^[0].b:='test3';//this is working...
 ShowMessage(v1[0].b);//shows test3
end;

end.

Я не понимаю, почему 'a ^ [0] .b: =' test2 'вызывает ошибку.

Спасибо!

Ответы [ 3 ]

10 голосов
/ 19 августа 2011

Ваша процедура 'Test' ожидает 'PRecArray', но вы передаете ей 'TRecArray'. Попробуйте назвать это как

 Test(@v1);//call method to change the value assigned before

Типирование 'TRecArray' к 'PRecArray' не сделает его 'PRecArray'. (Примечание: тогда ваш 'test3' потерпит неудачу.)

4 голосов
/ 19 августа 2011

Я вижу несколько подозрительных вещей.

1

Вряд ли когда-либо требуется указатель на динамический массив, поскольку переменные динамического массива уже являются указателями (ну, ссылки ).

Чтобы передать такой массив функции или процедуре, используйте var параметры:

procedure TForm1.Test(var a: TRecArray);

Теперь вам не нужно использовать синтаксис указателя для доступа к массиву:

a[0].b := 'test2';

2

Вы вызываете Test с помощью:

Test(PRecArray(v1));

В вашем оригинале Test принял PRecArray, но вы не передаете его (вы передаете TRecArray), поэтому вам следуетсделали:

Test(@v1); // or Test(Addr(v1));

Применяя мои изменения выше, где Test имеет параметр var, просто используйте:

Test(v1);

3

Хорошо, это вероятноне подозрительно, но я бы хотел добавить мою статью Addressing Pointers , посвященную указателям для программистов на Delphi.Это объясняет многие проблемы, которые у вас, похоже, есть.

1 голос
/ 19 августа 2011

Вы можете заменить

procedure TForm1.Test(a: TPointerArrayRec);

на

   procedure TForm1.Test(var a: TArrayRec);   

, это проще, и вам не нужно использовать оператор deprecation разыменования ^.

...