Page 1 of 1

Procedure problem

Posted: Mon May 05, 2003 3:59 pm
by talun
Dear all,

I'm stupid and I need your help.
Can anyone say me why in the following piece of code, the structure-member values are lost in the body of the Procedure test1?

Many thanks To all

Sergio

; ************************************************
Structure f3
a.f
b.f
c.f
EndStructure


Procedure test1(*x.f3,*y.f3)

Debug "Procedure Test1: input values:"
Debug "a: " + StrF(*x\a)
Debug "b: " + StrF(*x\b)
Debug "c: " + StrF(*x\c)
Debug "---------------------"

*y\a = *x\c
*y\b = *x\b
*y\c = *x\a

EndProcedure


Procedure test(*x.f3,*z.f3)

Debug "Procedure Test: input values:"
Debug "a: " + StrF(*x\a)
Debug "b: " + StrF(*x\b)
Debug "c: " + StrF(*x\c)
Debug "--------------------"

test1(@x.f3,@z.f3)

EndProcedure


DefType.f3 k, j

k\a = 1.1
k\b = 2.2
k\c = 3.3

Debug "Structure values before procedure call: "
Debug "a: " + StrF(k\a)
Debug "b: " + StrF(k\b)
Debug "c: " + StrF(k\c)
Debug "--------------"

test(@k.f3,@j.f3)


End
;****************************************
[/code]

Posted: Mon May 05, 2003 4:57 pm
by El_Choni
Change this line inside test procedure:

Code: Select all

test1(@x.f3,@z.f3)
for this one:

Code: Select all

test1(*x, *z)
Also, when giving a structure pointer as a parameter, you don't need to prefix it with '@' nor suffix it with the structure name (unless you're declaring the structure at that time), so this line:

Code: Select all

test(@k.f3,@j.f3)
can be changed to this one in your code (just for less typing, they work the same):

Code: Select all

test(k, j)

Posted: Tue May 06, 2003 8:35 am
by talun
Hi El_Choni,
many thanks for your reply. With your suggestions the code works fine but now I'm very confused.
Can anyone explain me why I need to use the "*" prefix and not the "@" address operator, as stated in the Pure Basic pointers help?
This is very important because it's very common to find calls between procedures with the same parameters.
Bye

Sergio

Posted: Tue May 06, 2003 10:23 am
by freak
The '@' gives you the memory address of an existing Variable,
where the '*' creates a pointer to an address in memory.

You can think of that pointer as kind of a 'virtual' variable, where
you can specify, which memory address it uses.

Let me give you an example: (turn debugger on)

Code: Select all

; firste we make a variable of POINT type ( a structure with x.l and y.l)
; this one gets it's own memory area reserved, and you can't change that.
Variable.POINT

; let's fill that one with some values:
Variable\x = 100
Variable\y = 625

; Now the '@' thing simply gives you the address, where the Variable is in memory
; let's have a look at that:
Debug @Variable

; at this address, there is now actually stored the X Value, and 4 bytes behind it, the
; y value of the Structure, you can see that with PeekL()
Debug PeekL(@Variable)
Debug PeekL(@Variable + 4)  ; 4 bytes after the X Value, because they are long.

; now, that is not the most comfortable way, to access the data, if we only know
; the address of it, there is a much better one.
; That is what the '*' is for. 

; We define a pointer to that Variable. We make it of the same type, so we can easily
; access the data inside.
*Pointer.POINT

; Now we have the pointer, but it points to nothing. To change the address, the pointer
; points to, we just write it like this:
*Pointer = @Variable

; Note, that you don't write any Members of the Structure here, this way, you can change
; the address of the pointer. As you can see, it points to the same address as the VAriable now:
Debug *Pointer

; Now, to access the data, we simply add the Member of the Structure we want to access. If
; a member is added, you get the Value that is stored in Memory, and not the Address itself anymore.
; See here:
Debug *Pointer\x
Debug *Pointer\y

; The Data can also be modified like that:
*Pointer\x = 22
*Pointer\y = 302

; As the pointer doesn't have it's own memory area, but just points to the one of the
; Variable, we actually changed the Values of the VAriable with the pointer here.
; see here;
Debug Variable\x
Debug Variable\y

So much for the basics, now for your actual Procedure thing:

Code: Select all

; We use the POINT structure again for explanation.
; Let's assume, we want to give a POINT Structure to a Procedure, how do we do that?
; Well, just the same, as I allready eyplained:
; give the address of the Variable with the Structure to the Procedure, and
; in the procedure, define a pointer, that can access this Variable later

; First, we make the procedure:

Procedure Test(*Pointer.POINT)
  ; The pointer get's defined, if the procedure is called, and is automatically
  ; set to the address we pass, when we call the procedure.
  
  ; Now we can access the data:
  Debug *Pointer\x
  Debug *Pointer\y
  
  ; Note: as this pointer actually points to the Variable in the main program, if we
  ; make changes here, they will be made on that Variable.
  ; This is not a bad thing, as it also allows some tricks, you just need to know that
  ; it works that way, to not make any hard to find mistakes.
  
  *Pointer\x = 5
  *Pointer\y * 1000

EndProcedure

; Now we make a VAriable of that Type:
Variable.POINT

; set some values
Variable\x = 120
Variable\y = 10

; now we call the procedure:
; here we need the address of the Variable, so the Pointer in the procedure will be set to this
; one.
Test(@Variable)

; now see the changed Values:
Debug Variable\x
Debug Variable\y
Hope that helps...

Timo

Posted: Tue May 06, 2003 12:31 pm
by Kale
A very clear explanation Timo, thanks :)

Posted: Tue May 06, 2003 4:23 pm
by talun
Timo,
thank you for your clear pointers tutorial. The El_Choni's and your replies have allowed me to solve my problems of parameter passing between procedures. They was related to undeclared data types and to the wrong use of the "@" prefix for assigned pointers.
Thanks! :D

Sergio