Pointers
Author Message
Pointers

Hello.. I'm trying to generate and use dynamic arrays
in a Turbo Pascal 7 program.  I've got the concepts figured
out, but seeing as Pascal doesn't allow pointer arithmetic, it
makes things quite a bit more difficult.  However, I wrote a
function to add values to a pointer base, in the hopes that that
would be the answer to my problems.  I must say, that it works
okay right now, as the following code would suggest, except
that between the first loop that generates random values and
stores them in my virtual array and the second which reads the
values back in and prints them out, about 50% of the data is
being corrupted.  When I tried adding the lines:
blah:= p^;
writeln(blah:3);
immediately after the "p^:= blah;" line in the first loop, the
values were fine (funny that, show, store, retrieve, show
doesn't modify the data!), but the simple process of starting
a new set of loops somehow sporadically corrupts some of my
data.  I've included the source code, sorry it's so long, but
I think you really need the whole picture to figure this one out.
Thanks in advance for any help or suggestions.

Quote:
>---- BEGIN PASCAL CODE ----<

program Dynamic_Array;

uses crt;

var
basep: pointer;
p: ^integer;
i,j,blah,size: word;

{-------------------------------------------------------------------------}
function addptr(baseval: pointer; stepval: integer): pointer;
var
sg,ofs: word;
begin
asm
mov bx, [bp+6]        { load the the stepval and the baseval }
les ax, [bp+8]
mov ofs, ax           { and store them }
mov sg, es
end;
addptr:= ptr(sg,ofs);   { create a pointer from the two parts }
end;    { of function }
{=========================================================================}

begin
size:= (11 * 11) * 2;   { see how big an array[0..10,0..10] of integers }
getmem(basep,size);     {  is and then allocate enough memory for one }
clrscr;

for i:= 0 to 10 do
for j:= 0 to 10 do
begin
p:= addptr(basep,(i * j) * 2);  { point at element in array }
blah:= random(30);              { get some gibberish }
write(blah:3);                  { display it }
p^:= blah;                      { store it (hopefully) in array }
end;    { of for }
writeln;

for i:= 0 to 10 do
for j:= 0 to 10 do
begin
p:= addptr(basep,(i * j) * 2);  { point at element in array }
blah:= p^;                      { (hopefully) get data }
write(blah:3)                   { display it }
end;    { of for }

freemem(basep,size);           { put the memory back on the heap }
repeat; until keypressed;
end.    { of main program }

Quote:
>---- END PASCAL CODE ----<

-chris gerber

Wed, 18 Jun 1902 08:00:00 GMT
Pointers

Quote:

>        Hello.. I'm trying to generate and use dynamic arrays
>in a Turbo Pascal 7 program.  I've got the concepts figured
>out, but seeing as Pascal doesn't allow pointer arithmetic, it
>makes things quite a bit more difficult.  However, I wrote a

[deription of problem dropped   ...red]

Quote:
>Thanks in advance for any help or suggestions.

[pascal code dropped ...red]

Quote:
>-chris gerber

Chris, when working with an untyped two dimensional array, you have
to multiply the first subscript by the number of elements in the
second dimension.

p := addptr(basep,(i * j) * 2);  { point at element in array }

Should be:

p := addptr(basep, ((i * 11{max "I" items} + j) * 2{Size of 1 item};

You also asked for suggestions, so here are a few:
Your AddPtr function is more complex than it needs to be. It could
be simplified as:

Function AddPtr(BaseVal: Pointer; StepVal: integer): Pointer;
Assembler;
asm
les AX, [BaseVal]
mov DX, ES
End;

It takes 5 bytes to call a FAR procedure and 5-bytes for this to be
coded as an inline routine, so a library function could be defined
as inline without increasing the size of the program:

Function AddPtr(BaseVal: Pointer; StepVal: integer): Pointer;
INLINE (\$59        { pop CX    }
/\$58        { pop AX    }
/\$5A        { pop DX    }
/\$03 /\$C1   { add AX,CX }
);

You can also do some simple pointer arithmetic by using a little
type casting

p := Ptr(Seg(BaseP^), Ofs(BaseP^) + (i*11 +j) * Sizeof(Integer));

Since you have version 7.0, you can enable extended syntax and let the
compiler do the pointer arithmetic for you. Add {\$X+} at the beginning
of the program, define a TYPE tpInteger = ^Integer then use one of the
following;

p := tpInteger(pChar(BaseP) + (i*11+j)*2);

If you define baseP as a pChar then you can drop the pChar type cast.

p := tpInteger(BaseP + (i*11+j)*2);

If you know for certain that the array will be an array of integers
you can define BaseP as a ^Integer then you can drop both type casts.
Note that we no longer have to multiply by 2 or Sizeof(Integer). That
information is now contained in BaseP and properly handled by the 7.0
compiler:

p := BaseP + (i * 11 + j);

Extended syntax also allows use to Inc and Dec pointers.
For example:

p := tpInteger(BaseP);     { Or define BaseP and ^Integer }
Inc(p, i * 11 + j);        { compiler adjustes for Sizeof(p^) }
{ hence *2 or Sizeof(Integer) dropped }

This lesson on pointer arithmetic is brought to you by the variables i
and j and the pointer p. <g>

Joking aside, I hope this strengthens your understanding and ability
to manipulate pointers.  You've got a fair start and the courage to
experiment so I'm sure you'll have it mastered in no time.

...red

Wed, 18 Jun 1902 08:00:00 GMT
Pointers

Quote:
Gerber) writes:

[...Snip...]

Quote:
>{-------------------------------------------------------------------------}
>function addptr(baseval: pointer; stepval: integer): pointer;
>var
>  sg,ofs: word;
>begin
>  asm
>    mov bx, [bp+6]        { load the the stepval and the baseval }
>    les ax, [bp+8]
>    mov ofs, ax           { and store them }
>    mov sg, es
>  end;
>  addptr:= ptr(sg,ofs);   { create a pointer from the two parts }
>end;    { of function }
>{=========================================================================}

Chris, there is a much easier and faster way to do pointer arithmatic in TP, as
long as you don't want to cross segment boundaries. The code below works in both
real and (16-bit) protected mode....

Type
PtrRec = record
Ofs: Word;
Seg: Word;
end;

begin
.
.
Inc(PtrRec(BaseVal).Ofs, StepVal);
.
.
end;

Note that it works by typecasting the pointer into a PtrRec and then StepVal is

More often, if you had an array of TMyType and wanted to index the next element
in the array you would use something like...

Inc(PtrRec(BaseVal).Ofs, SizeOf(TMyType));

This compiles to a single assembler Add instruction.

BTW, the PtrRec type is defined in the OBJECTS.PAS unit, so if you "Uses
Objects", you won't have to define it in your own program.

-- Jay

---------------------------------------------------------------------------
| Jason Burgon - author of Graphic Vision, TV-Like GUI for 256 Colour SVGA  |

|                         http://www.en.com/users/grendel/prog/tv_prog.html |
---------------------------------------------------------------------------

Wed, 18 Jun 1902 08:00:00 GMT
Pointers

Quote:
>        Hello.. I'm trying to generate and use dynamic arrays
>in a Turbo Pascal 7 program.  I've got the concepts figured
>out, but seeing as Pascal doesn't allow pointer arithmetic, it
>makes things quite a bit more difficult.

If the pointer is a pointer to a type then :

Type
TMyType = Record
.
.
End;
PMyType = ^TMyType;

Var
baseptr, temptr : PMyType;

temptr := Baseptr;
Inc(temptr, numtoinc);

Will increment the pointer the proper number of bytes.

If it's just declared as a pointer then :

temptr := Pointer(LongInt(baseptr) + num * sizeof(TSomething));

Wed, 18 Jun 1902 08:00:00 GMT

 Page 1 of 1 [ 4 post ]

Relevant Pages