Board index » delphi » passing pointers as procedure parameters

passing pointers as procedure parameters

In article <MPG.14812d338af2df84989...@news.nzl.ihugultra.co.nz>,
  Peter Huebner <peterh@this_bounces.igrin.co.nz> wrote:

Quote

> I have very little experience of using pointers in Delphi.
> I tried the other day to pass a pointer to an element in
> a dynamic array of MyRecordType to a procedure, then
> change the values of some of the fields in the procedure.
> I got absolutely nowhere - the code I wrote compiled just
> fine, but the values did not appear in the array after
> the procedure had executed.

> 1. attempt:
> -----------
> procedure TLedger.PokeSomeValues(AnItem: ^MyRecordType);
> begin
>   AnItem^.account := somestring;
>   AnItem^.flag1   := true;
>   AnItem^.flag2   := false;
>   AnItem^percent  := 55;
> end;

> When I did a break all the assigned values were empty.

Is this exactly the code you used? It doesn't even compile
for me - the error is at the  ^MyRecordType:

"Type identifier expected, ^ found".

If I fix that it works just fine - maybe the problem is
in the syntax of the call or something. Try this:

type
     PMyRecordType = ^TMyRecordType;
     TMyRecordType = record
       n, m: integer;
     end;

procedure InsertAnswer(ARecord: PMyRecordType);
begin
  ARecord^.n:= 42;
  ARecord^.m:= 42;
end;

procedure TForm1.Button1Click(Sender: TObject);
var r: TMyRecordType;
begin
  InsertAnswer(@r);
  ShowMessage(inttostr(r.n) + ' = ' + inttostr(r.m));
end;

It works for me. You can leave out some of the ^'s, btw.

If you have an actual reason for using pointers here you
must be allocating memory. You'd call InsertAnswer with
a dynamically-allocated TMyRecordType like so:

procedure TForm1.Button2Click(Sender: TObject);
var p: PMyRecordType;
begin
  New(p);
  InsertAnswer(p);
  ShowMessage(inttostr(p.n) + ' = ' + inttostr(p.m));
  Dispose(p);
end;

That works for me too.

But I don't think there's really any reason to use pointers
in the procedure. Instead I'd say

procedure VarInsertAnswer(var ARecord: TMyRecordType);
begin
  ARecord.n:= 42;
  ARecord.m:= 42;
end;

and I'd call that as in either

procedure TForm1.Button3Click(Sender: TObject);
var r: TMyRecordType;
begin
  VarInsertAnswer(r);
  ShowMessage(inttostr(r.n) + ' = ' + inttostr(r.m));
end;

or

procedure TForm1.Button4Click(Sender: TObject);
var p: PMyRecordType;
begin
  New(p);
  VarInsertAnswer(p^);
  ShowMessage(inttostr(p.n) + ' = ' + inttostr(p.m));
  Dispose(p);
end;

Not sure what the problem in your code is - what you posted
didn't compile for me, and when I fixed that what I got made
me think the problem could be in the parts you're not
showing us. But everything above works.

--
Oh, dejanews lets you add a sig - that's useful...

Sent via Deja.com http://www.deja.com/
Before you buy.

 

Re:passing pointers as procedure parameters


I have very little experience of using pointers in Delphi.
I tried the other day to pass a pointer to an element in
a dynamic array of MyRecordType to a procedure, then
change the values of some of the fields in the procedure.
I got absolutely nowhere - the code I wrote compiled just
fine, but the values did not appear in the array after
the procedure had executed.

1. attempt:
-----------
procedure TLedger.PokeSomeValues(AnItem: ^MyRecordType);
begin
  AnItem^.account := somestring;
  AnItem^.flag1   := true;
  AnItem^.flag2   := false;
  AnItem^percent  := 55;
end;

When I did a break all the assigned values were empty.

The same happened when I passed array and index!

2. attempt:
-----------
procedure TLedger.PokeSomeValues(MyArray: array of MyRecordType,                                                                                              
                                     index:short);
begin
  MyArray[index].account := somestring;
  et cetera;
end;

Again, no joy. Now, I know that the array does not get passed to
the routine, actually instead a pointer to the start of the array.
Still, this should've worked, theoretically, yes/no?

3. attempt:
-----------
function TLedger.PokeSomeValues(AnItem: MyRecordType): MyRecordType;
begin
  PokeSomeValues.account := AnItem.account;
  PokeSomeValues.percent := query2.fieldbyname('depreciation').asinteger;
  PokeSomeValues.sum     := AnItem.sum;
  et cetera;
end;  

I managed by rewriting the procedure as a function, and passing
the element of the array that I wanted changed, but I am still
curious to know what I did wrong in my first, and second effort. I
used to use constructions like the first one very effectively in a
different language some years ago.

I would be grateful if somebody could shed some light...

TIA,   -Peter

--

Please note munged reply address - delete the obvious ....

Re:passing pointers as procedure parameters


Quote
Peter Huebner <peterh@this_bounces.igrin.co.nz> wrote in message

news:MPG.14812d338af2df84989686@news.nzl.ihugultra.co.nz...

Quote

> I have very little experience of using pointers in Delphi.
> I tried the other day to pass a pointer to an element in
> a dynamic array of MyRecordType to a procedure, then
> change the values of some of the fields in the procedure.
> I got absolutely nowhere - the code I wrote compiled just
> fine, but the values did not appear in the array after
> the procedure had executed.

> 2. attempt:
> -----------
> procedure TLedger.PokeSomeValues(MyArray: array of MyRecordType,
>                                      index:short);
> begin
>   MyArray[index].account := somestring;
>   et cetera;
> end;

> Again, no joy. Now, I know that the array does not get passed to
> the routine, actually instead a pointer to the start of the array.
> Still, this should've worked, theoretically, yes/no?

Two points.

a) procedure TLedger.PokeSomeValues(MyArray: array of MyRecordType, index
short);

Whether Delphi actually passes a copy of the array or not, it certainly acts
like it is writing to a local copy, and you have to use
 procedure TLedger.PokeSomeValues( var MyArray: array of MyRecordType, index
short);

b) you are using open array syntax, and regardless of how you have to
declared MyArray,  it is indexed from 0..whatever within the procedure.

Dave

Re:passing pointers as procedure parameters


Im Artikel <MPG.14812d338af2df84989...@news.nzl.ihugultra.co.nz>, Peter Huebner
<peterh@this_bounces.igrin.co.nz> schreibt:

Quote
>procedure TLedger.PokeSomeValues(AnItem: ^MyRecordType);

Instead I'd use:

procedure TLedger.PokeSomeValues(var AnItem: MyRecordType);

The "var" keyword results in a reference to the data, i.e. a "disguised"
pointer.

DoDi

Re:passing pointers as procedure parameters


Quote
"Peter Huebner" <peterh@this_bounces.igrin.co.nz> wrote in message

news:MPG.14812d338af2df84989686@news.nzl.ihugultra.co.nz...

Quote

> I have very little experience of using pointers in Delphi.
> I tried the other day to pass a pointer to an element in
> a dynamic array of MyRecordType to a procedure, then
> change the values of some of the fields in the procedure.
> I got absolutely nowhere - the code I wrote compiled just
> fine, but the values did not appear in the array after
> the procedure had executed.

> 1. attempt:
> -----------
> procedure TLedger.PokeSomeValues(AnItem: ^MyRecordType);
> begin
>   AnItem^.account := somestring;
>   AnItem^.flag1   := true;
>   AnItem^.flag2   := false;
>   AnItem^percent  := 55;
> end;

You can't go making up types on the fly like that. If you REALLY want
to do it with a pointer, you need to declare the pointer type first:

Type
  PMyRecordType = ^MyRecordType;
procedure TLedger.PokeSomeValues(AnItem: PMyRecordType);

in order to get it to compile. But using a Var parameter might be
better.

Quote
> When I did a break all the assigned values were empty.

> The same happened when I passed array and index!

> 2. attempt:
> -----------
> procedure TLedger.PokeSomeValues(MyArray: array of MyRecordType,

PokeSomeValues(Var MyArray...

FP

Re:passing pointers as procedure parameters


Quote
"Peter Huebner" <peterh@this_bounces.igrin.co.nz> wrote in message

news:MPG.14812d338af2df84989686@news.nzl.ihugultra.co.nz...

Quote

> I have very little experience of using pointers in Delphi.
> I tried the other day to pass a pointer to an element in
> a dynamic array of MyRecordType to a procedure, then
> change the values of some of the fields in the procedure.
> I got absolutely nowhere - the code I wrote compiled just
> fine, but the values did not appear in the array after
> the procedure had executed.

> 1. attempt:
> -----------
> procedure TLedger.PokeSomeValues(AnItem: ^MyRecordType);
> begin
>   AnItem^.account := somestring;
>   AnItem^.flag1   := true;
>   AnItem^.flag2   := false;
>   AnItem^percent  := 55;
> end;

> When I did a break all the assigned values were empty.

> The same happened when I passed array and index!

As David Ulrich pointed out, the above won't compile.

Quote

> 2. attempt:
> -----------
> procedure TLedger.PokeSomeValues(MyArray: array of MyRecordType,
>                                      index:short);
> begin
>   MyArray[index].account := somestring;
>   et cetera;
> end;

> Again, no joy. Now, I know that the array does not get passed to
> the routine, actually instead a pointer to the start of the array.
> Still, this should've worked, theoretically, yes/no?

Your assumption that the array doesn't get passed is wrong. You have
specified a "pass by value" parameter so a copy of the array is used within
the procedure.

- Show quoted text -

Quote

> 3. attempt:
> -----------
> function TLedger.PokeSomeValues(AnItem: MyRecordType): MyRecordType;
> begin
>   PokeSomeValues.account := AnItem.account;
>   PokeSomeValues.percent := query2.fieldbyname('depreciation').asinteger;
>   PokeSomeValues.sum     := AnItem.sum;
>   et cetera;
> end;

> I managed by rewriting the procedure as a function, and passing
> the element of the array that I wanted changed, but I am still
> curious to know what I did wrong in my first, and second effort. I
> used to use constructions like the first one very effectively in a
> different language some years ago.

Once again you have specified a "pass by value" mechanism, so a copy of the
actual parameter is passed.

Quote

> I would be grateful if somebody could shed some light...

I'd suggest you check out the Object Pascal Reference, particularly the
section that deals with parameter passing mechanisms available in OP.

Unlike C, there is no need to use pointers for parameters in Pascal. Pascal
has a "pass by reference" mechanism the handles this for you.

Re:passing pointers as procedure parameters


Well there is lots of fun in Object Pascal :). One of the problems I find
with using help indexes is that one needs to know the right keywords in
order to find the information one is looking for. As you discovered, that
isn't always an easy task.

I've found the Object Pascal Reference to be one of the most useful pieces
of documentation in the help files. It does a relatively good job of
describing the language syntax and semantics. If you haven't done so
already, I'd suggest using the help table of contents to access the file and
go through it from start to finish. There really is a lot of valueable
information there that will help you to become fluent in OP.

Re:passing pointers as procedure parameters


In article <fsBS5.297$tj4.1...@tor-nn1.netcom.ca>,
b...@bounceitattcanada.xnet says...

Quote
> I'd suggest you check out the Object Pascal Reference, particularly the
> section that deals with parameter passing mechanisms available in OP.

Yupp - except <g>

  let me put it this way: I spent half a day searching Delphi helpfiles
looking for 'procedures''parameters''passing''value''reference', w.h.y. and
didn't find what I was looking for until I turned to the NG ..... after the
first replies started trickling in ( and thank you all ) I finally thought
to look under "routines" and  finally struck gold - all that info I had't
been able to locate before. So it goes ;-)

From what I had read previously I had gathered that objects like records and
dynamic arrays _always_ get passed as a 32 bit pointer and then dereferenced
so I had jumped to the wrong conclusion that this would work in reverse
as well .... live and learn, that's half the fun of it. I am only just
beginning to dip into the layers below the layers in Delphi ( & O.P.).

cheers, -P.

--

Please note munged reply address - delete the obvious ....

Other Threads