Reading specific bytes from portion of heap (pointers for "array") 
Author Message
 Reading specific bytes from portion of heap (pointers for "array")

I am rather stumped with usage of pointers in TP7, and I am thinking
that what I am trying to do is not possible in Pascal, only something
like C (which I dont know very well).  Hopefully someone will prove me
wrong....

I found code on the Turbo Pascal Links page to load a BMP file, which
drew the bitmap to the screen as it read it from file.  Of course this
is very slow, and very stupid if the same graphic is to be displayed
many times.  So I quickly modified it to cache the bitmaps into
variables, then a separate procedure would draw it from memory onto
the screen.  So far so good, but in the declaration of types I was
left with:

BMPFile = Record
   header : tbmpheader;
   data : array[1..16,1..16] of byte;
end;

which of course restricts me to a BMP of 16*16.  I wanted to find a
way of being able to cache BMPs of varying sizes, and since Pascal has
no equivalent of VB's ReDim to change array size, I looked at
pointers.  I soon got as far as declaring  
  data : ^Byte;
and allocating the appropriate amount of memory for the data by doing:

{ reads header here }
getmem(MyBMP.data,MyBMP.header.height*myBMP.header.width);

Again, so far so good, but now as I loop through the data in the file,
how can I place each byte into MyBMP.data^ ?  At first I thought of
merely incrementing the address in the pointer so each byte would be
placed one byte further on in memory:

BlockRead(BMPFile, Pixel, SizeOf(Pixel));  {reads byte from the file}
inc(MyBMP.data); {increments location to store it in}
MyBMP.data^ := Pixel; {store it in memory}

This was not very satisfactory, since I 'lose' the original address
denoting the 'start' of the memory pointed to in MyBMP.data.  Instead
I tried doing this:

TempP := MyBMP.data;  { where tempP is ^byte }
{ snip }
inc(TempPointer);

...so I can increment another pointer and not lose the original
address.  Pascal simply refused to give TempP the address that
MyBMP.data points at.  In fact, it resisted all attempts to find out
what that address was at all... it would not let me copy the address
into an integer variable, writeln it to the screen, or anything...
The idea was, for example, to find the value of the bitmap's fourth
pixel:

memory address for 'start' of data + four

But, it seems I must only ask of it MyBMP.data^ and never MyBMP.data
itself... but without some way of getting the actual memory address, I
cannot figure out how to access a specific byte of memory.  

I am probably missing something extremely obvious!  Feel free to
ridicule me if I am :)  But I hope someone can help, else I'll have to
learn C.  ;)

-stephen

--------
My monument to style over content:
http://www.*-*-*.com/



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")
Quote:

> I am rather stumped with usage of pointers in TP7, and I am thinking
> that what I am trying to do is not possible in Pascal, only something
> like C (which I dont know very well).  Hopefully someone will prove me
> wrong....

---snip

This mail is a typical example of how it shall not be done...

Pascal is per definition a language for learning purposes,
and it is principally not intended for power improvements
with brute force.

You shall first learn how to do "correct" and "beautiful"
programming, using the rules. Later, if you are familiar
with all the ideas behind, you can slowly begin to use
tricks.

Your behaviour is well suited for "C" programming, please
do it!

Franz Glaser



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:

>This was not very satisfactory, since I 'lose' the original address
>denoting the 'start' of the memory pointed to in MyBMP.data.  Instead
>I tried doing this:

>TempP := MyBMP.data;  { where tempP is ^byte }
>{ snip }
>inc(TempPointer);

TempP and TempPointer are different identifiers.

Osmo



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")


Quote:
>TempP and TempPointer are different identifiers.

Ah thats just a typo, they are the same in the actual code.


Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")
On Sun, 04 Oct 1998 22:34:18 +0100, "Ing. Franz Glaser"

Quote:

>Your behaviour is well suited for "C" programming, please
>do it!

If I first learn C.... :/


Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:

> You shall first learn how to do "correct" and "beautiful"
> programming, using the rules. Later, if you are familiar
> with all the ideas behind, you can slowly begin to use
> tricks.

To give at least one useful hint: Look for variant records
in Pascal.

Franz Glaser



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:

>I am rather stumped with usage of pointers in TP7, and I am thinking
>that what I am trying to do is not possible in Pascal, only something
>like C (which I dont know very well).  Hopefully someone will prove
me
>wrong....

I hope so too. You can do almost anything with the pointers in Borland
Pascal, apart from adding integers to them or accessing single blocks
of memory > 64k. For the latter you'll need FPC or one of those
protected mode compilers. I'll have to hope I don't miss the point of
your message in this reply and answer the wrong question...

Quote:
>...
>I tried doing this:

>TempP := MyBMP.data;  { where tempP is ^byte }
>{ snip }
>inc(TempPointer);

>...so I can increment another pointer and not lose the original
>address.  Pascal simply refused to give TempP the address that
>MyBMP.data points at.

This is puzzling. You are saying TempP := MyBmp.Data will not compile?
Where both TempP and MyBmp.Data are ^Byte? It works fine on my one.
What error message are you getting? Could you still have the _old_
definition of MyBmp (where Data was an array, not a pointer) in scope?

By the way,

Quote:
>  In fact, it resisted all attempts to find out
>what that address was at all... it would not let me copy the address
>into an integer variable, writeln it to the screen, or anything...

Copying it to an integer is a bad idea, even in C. If it's a pointer,
you can copy its value to a variable of type Pointer. But your
problems suggest that the compiler thinks it's not a pointer. You are
correct that you cannot writeln pointers, although you can writeln
seg(MyBmp.Data^) and ofs(MyBmp.Data^) in decimal -- if Data is really
a pointer -- or use a function like

Function Hex(i:LongInt; Lgt:Byte):String;
Const HexDigs:Array[0..15] of Char = '0123456789ABCDEF';
Var s : String;
Begin
  s := '';
  Repeat
    s := HexDigs[i and $F] + s;
    i := i shr 4;
  until (i = 0) and (length(s) >= Lgt);
  Hex := s;
End;

to write those values out in hex. Can you get the address of Data
using Addr(MyBmp.Data) or the like? What does Addr(MyBmp.Data^)
compile as?

Quote:
>The idea was, for example, to find the value of the bitmap's fourth
>pixel:

>memory address for 'start' of data + four

I don't think you can add integers to pointers in Pascal. But you can
declare
Type
  ptArByte = ^tArByte;
  tArByte = Array[0..MaxInt*2] of Byte;
and declare MyBmp.pData to be ptArByte instead. Then you can use
MyBmp.pData^[4] to get that byte. (I'm calling it pData to distinguish
it from the Array version at the start of your post.)

Quote:
>But, it seems I must only ask of it MyBMP.data^ and never MyBMP.data
>itself... but without some way of getting the actual memory address,
I
>cannot figure out how to access a specific byte of memory.

MyBmp.Data should be an address already. But an address is not an
integer, especially on the 80x86's segmented architecture. If you
_really_ want to, you could use Ptr(seg(p^), ofs(p^)+n) where p is a
pointer and n an integer, and watch out for overflows!

Quote:
>I am probably missing something extremely obvious!  Feel free to
>ridicule me if I am :)

Not necessarily obvious, and I won't because they'd do it to me too.
What you are trying to do certainly sounds possible in TurboPascal, if
the answers you get here don't solve the problem please rephrase the
question rather than giving up.

FP



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:

>I don't think you can add integers to pointers in Pascal.

When I wrote that, the Inc operator didn't occur to me. It works fine
on pointers, even pointers other than pChar. AFAIK it's only
documented for pchar. But the following works fine (the Hex function
referred to was in my previous post):

Function PtrS(p:Pointer):String;
Begin
  PtrS := Hex(Seg(p^),4)+':'+Hex(Ofs(p^),4);
End;

Type
  t = record
    l : LongInt;   { any stuff }
    s : String;
  End;

Var
  p : ^t;
Begin
  Writeln('Size of t = ',hex(SizeOf(t),0),'h');
  p := Ptr($1000, $0);
    { This value for illustration only. p will NOT be dereferenced!
    }
  Writeln('                  p : ',PtrS(p));
  Inc(p);
  Writeln('    Incremented once: ',PtrS(p));
  Inc(p, 15);
  Writeln('Incremented 16 times: ',PtrS(p));
    { 15 in this inc + once in the previous one
    }
End.

FP



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:

>This mail is a typical example of how it shall not be done...

>Pascal is per definition a language for learning purposes,

That may have been true 25 years ago. But it's not what the Borland
compilers were defined or created for.

FP



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

...

Quote:

>>...so I can increment another pointer and not lose the original
>>address.  Pascal simply refused to give TempP the address that
>>MyBMP.data points at.

>This is puzzling. You are saying TempP := MyBmp.Data will not compile?
>Where both TempP and MyBmp.Data are ^Byte? It works fine on my one.

Actually it doesn't and should not work., The fact that two variables
are defined in a similar way does not make them compatible.

var p:^byte;
    q:^byte;

begin
  p:=q;
end.

Gives Type mismatch as it should. In above case one could define

var p,q:^byte;

but a better solution is to define a type. I repeat it as it is so
crucial to Pascal programming in general DEFINE A TYPE!

type Pbyte;

var p:Pbyte;
    q:Pbyte;
...

In general one should always define types and not use pointer, array or
record declarations in variable definitions.

Osmo



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:



>...

>>>...so I can increment another pointer and not lose the original
>>>address.  Pascal simply refused to give TempP the address that
>>>MyBMP.data points at.

>>This is puzzling. You are saying TempP := MyBmp.Data will not
compile?
>>Where both TempP and MyBmp.Data are ^Byte? It works fine on my one.

>Actually it doesn't and should not work., The fact that two variables
>are defined in a similar way does not make them compatible.

>var p:^byte;
>    q:^byte;

>begin
>  p:=q;
>end.

>Gives Type mismatch as it should. In above case one could define

I have just cut&pasted that code fragment into BP7 and compiled it,
there was no error message (I would have been surprised if there had
been an error since I had compiled essentially the same code before
posting the first time.

Could it be a compiler option? I have
{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S-,T+,V+,X+,Y+} but it
compiles with X- as well.

But you're right about defining a type for it, saves a lot of hassle.

FP



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:


>>Actually it doesn't and should not work., The fact that two variables
>>are defined in a similar way does not make them compatible.

>>var p:^byte;
>>    q:^byte;

>>begin
>>  p:=q;
>>end.

>>Gives Type mismatch as it should. In above case one could define

>I have just cut&pasted that code fragment into BP7 and compiled it,
>there was no error message (I would have been surprised if there had
>been an error since I had compiled essentially the same code before
>posting the first time.

>Could it be a compiler option? I have
>{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S-,T+,V+,X+,Y+} but it


operator and so that with $T+ it is typed and with $T- untyped. What you
have noticed is IMO a bug. It should not pass. Also $T+ should be a
stricter check, not a looser one.

Osmo



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")


Quote:
>This is puzzling. You are saying TempP := MyBmp.Data will not compile?
>Where both TempP and MyBmp.Data are ^Byte? It works fine on my one.
>What error message are you getting?

Type mismatch - as Osmo Ronkanen explained...

Quote:
>Copying it to an integer is a bad idea, even in C. If it's a pointer,
>you can copy its value to a variable of type Pointer. But your
>problems suggest that the compiler thinks it's not a pointer. You are
>correct that you cannot writeln pointers, although you can writeln
>seg(MyBmp.Data^) and ofs(MyBmp.Data^) in decimal -- if Data is really
>a pointer -- or use a function like

Bad idea? Ok :)  I was just getting *ahem* inventive.  seg and ofs are
unknown to me, I'll give them a try...

Quote:
>I don't think you can add integers to pointers in Pascal.

You can with inc (as you remembered in another post).

Quote:
>MyBmp.Data should be an address already. But an address is not an
>integer, especially on the 80x86's segmented architecture.

Ah.  Shows how much I know *sigh*

Quote:
>Not necessarily obvious, and I won't because they'd do it to me too.
>What you are trying to do certainly sounds possible in TurboPascal, if
>the answers you get here don't solve the problem please rephrase the
>question rather than giving up.

Thanks for the help (certainly more use than lectures on my
"attitude", which without meaning to be rude, I didnt particularly
appreciate).  I'll try your suggestions and post again if I get any
results.

-Stephen

----------------------------
"Eagles may soar, but weasels aren't sucked into jet engines."

The Flatworld - http://www.flatworld.u-net.com/home.htm



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")


Quote:
>I don't think you can add integers to pointers in Pascal. But you can
>declare
>Type
>  ptArByte = ^tArByte;
>  tArByte = Array[0..MaxInt*2] of Byte;
>and declare MyBmp.pData to be ptArByte instead. Then you can use
>MyBmp.pData^[4] to get that byte. (I'm calling it pData to distinguish
>it from the Array version at the start of your post.)

Ah, I just re-read your post, and discovered this which I missed when
I wrote my first reply.  This would appear to be exactly what I am
after... but I have another question... (again, I think I must be
missing something obvious ;))

If MaxInt is a constant (32767) then surely that code would just be
declaring a static sized array (~64000 bytes in size).  What advantage
would this have over declaring a static array in the normal way:

data : array[1..whatever,1..whatever] of byte;

Because surely I am still setting aside x bytes of memory, when I
might possibly only be using y bytes.  The intention was to only use
the memory needed... and avoid "declare the largest thing it could
possibly be" type statements.

Thanks for the help,
stephen



Wed, 18 Jun 1902 08:00:00 GMT  
 Reading specific bytes from portion of heap (pointers for "array")

Quote:



>>...
>>Type
>>  ptArByte = ^tArByte;
>>  tArByte = Array[0..MaxInt*2] of Byte;
>...

>If MaxInt is a constant (32767) then surely that code would just be
>declaring a static sized array (~64000 bytes in size).  What
advantage
>would this have over declaring a static array in the normal way:

>data : array[1..whatever,1..whatever] of byte;

No, I wasn't suggesting that a 64K array should be created, only that
such a type declaration would be helpful. The tArByte type would never
be instantiated. It is only used to define ptArByte, to tell the
compiler all about what a ptArByte should be pointing at. Maybe the
declaration could be done in one line but I get confused if I try to
do too many things in one step. You don't know, at compile time, how
many bytes are going to be allocated. You would allocate memory with
GetMem to a ptArByte variable and then use only those elements for
which you had allocated memory. So the array that the ptArByte points
to can have any number of elements - but it cannot be greater than
MaxInt*2 with the Borland compiler (probably FPC etc. can do better).
Some people prefer to use and array[0..0] but I prefer to use a large
upper bound so that I can leave range-checking on for the rest of my
program, and so that I know the compiler can handle arrays that big.

As in C, a multidimensional array where more than one dimension is
unknown at compile time is not possible. You can create an array on
the heap with the number of elements determined at run-time, but the
size of each element must be known at compile time if the compiler is
to be able to work out how to index elements in the array. A
2-dimensional array is laid out as an array where each element is an
array - if the size of the latter array is not known, that's the same
as saying that the former array is one whose element size is unknown.

FP



Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. The keys "-"/"+"/"*"

2. "Parsing" through bits in a byte

3. ""256 Color Mouse""

4. FP106: Error: Incompatible types: got "BYTE" expected "SHORTSTRING"

5. "Index is read only"?

6. Delphi 2: "Index is Read Only"

7. "Like" returns read-only dataset

8. Reading "Sounds" in

9. BDE Error - "not exact read/write"?

10. test "?"..do not bother to read....

11. BDE Error "Not exact read/write"

12. "NEED CASH $$$$$ READ HERE $$$$$"

 

 
Powered by phpBB® Forum Software