Page 1 of 1

Basic Pointer Problem -- Pointer treated as simple variable

Posted: Mon Apr 27, 2020 9:35 pm
by glennj.0158
I'm familiar with pointers from C and expected the following to work. It didn't and I don't see my problem.

Code: Select all

 Procedure	Sample (A.d, B.d, *c.Point )
 	Debug "Value of *c in Sample() before assignment"
	Debug *c
	*c = A * B		;Store the result in the variable pointed to by *c
	Debug "Value of *c in Sample() after assignment"
	Debug *c
EndProcedure

Define	Cval.d
Define.Point	*C
*C = @CVal			;Pointer *C = Address of (Cval)
Debug "Value of *C in Main()"
Debug *C

Sample (2, 4, *C)

Debug "Value of *C in Main()"
Debug *C
Debug "Value of Cval in Main()"
Debug Cval
	End
The Debug output is
Value of *C in Main()
5368967144
Value of *c in Sample() before assignment
5368967144
Value of *c in Sample() after assignment
8
Value of *C in Main()
5368967144
Value of Cval in Main()
0.0

So I get the address into *C in main() but in Sample() the variable *C is treated like a normal variable and not a pointer. I've clearly messed up the declaration of *C as a pointer but I don't see how.

Thanks

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Mon Apr 27, 2020 9:45 pm
by NicTheQuick
There is no dereferencing in Purebasic. If you assign a value to a plain variable or to a pointer variable *c, you only changed the address the pointer points to.
If you want to change the value at the address where the pointer points to, you either have to use PokeD(*c, 123.456) for a single value or in your case you can use the structure fields of the Point structure, which are *c\x and *c\y. But also remember that the Point structure consists of to 16 bit words instead of two doubles. It is a predefined structure from Windows.

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Mon Apr 27, 2020 10:12 pm
by skywalk
I don't know what you are trying to do, but this shows pass ByRef.

Code: Select all

Structure PointD
  x.d
  y.d
EndStructure
Procedure Sample(A.d, B.d, *c.PointD)
  *c\x = A * B
  *c\y = A * B
  Debug "Value of *c in Sample() after assignment"
  Debug *c\x
  Debug *c\y
EndProcedure
Define cVal.PointD
Define.PointD *c
*c = @cVal
Debug "Value of *c in Main()"
Debug *c\x
Debug *c\y
Sample(2, 4, *c)
Debug "Value of *c in Main()"
Debug *c\x
Debug *c\y
Debug "Value of cVal in Main()"
Debug cVal\x
Debug cVal\y
Sample(1, 2, @cVal)
Debug "Value of *c in Main()"
Debug *c\x
Debug *c\y
Debug "Value of cVal in Main()"
Debug cVal\x
Debug cVal\y

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Mon Apr 27, 2020 10:13 pm
by Demivec
How about this modified version of your code sample:

Code: Select all

;This structure is already predefined
;Structure Double
;  d.d
;EndStructure

 Procedure	Sample (A.d, B.d, *c.Double )
 	Debug "Value of *c in Sample() before assignment"
	Debug *c/d
	*c/d = A * B		;Store the result in the variable pointed to by *c
	Debug "Value of *c in Sample() after assignment"
	Debug *c/d
EndProcedure

Define	Cval.d
Define.Double	*C
*C = @CVal			;Pointer *C = Address of (Cval)
Debug "Value of *C in Main()"
Debug *C/d

Sample (2, 4, *C)

Debug "Value of *C in Main()"
Debug *C/d
Debug "Value of Cval in Main()"
Debug Cval
	End

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Wed Apr 29, 2020 2:32 am
by glennj.0158
Hi all

What I'm trying for is Call-By-Reference, where the address of an external variable is passed into the procedure and the procedure acts directly on the external variable.

What I was expecting to happen was that by defining *c.Point I would pass the address of the external variable into the procedure and then *c = Value would actually store the value into the location pointed to by the address contained in *c

The example using PokeD(*c, 123.456) {from NicTheQuick} seems like the most direct way to get the effect I was looking for.

Thanks everyone

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Wed Apr 29, 2020 6:30 am
by Little John
In PureBasic, pass by reference works e.g. like this (no need to use Poke()):

Code: Select all

Procedure ChangeInt (*a.Integer)   ; 'Integer' is a predefined structure
   *a\i + 3                        ; change value of the variable
EndProcedure

Define x.i
x = 7
ChangeInt(@x)
Debug x                            ; displays 10
With strings it works a bit differently.
Arrays, lists and maps are always passed to procedures by reference anyway.

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Wed Apr 29, 2020 12:19 pm
by mk-soft
Tip and Tricks

VarType 'Any' and 'AnyArray'

Code: Select all

;-TOP

Structure Any
  StructureUnion
    a.a
    b.b
    c.c
    w.w
    u.u
    l.l
    i.i
    q.q
    f.f
    d.d
  EndStructureUnion
EndStructure

Structure AnyArray
  StructureUnion
    a.a[0]
    b.b[0]
    c.c[0]
    w.w[0]
    u.u[0]
    l.l[0]
    i.i[0]
    q.q[0]
    f.f[0]
    d.d[0]
  EndStructureUnion
EndStructure

; ----

Procedure foo(*value.any, Type)
  
  Select Type
    Case #PB_Integer
      Debug *value\i
    Case #PB_Double
      Debug *value\d
  EndSelect
  
EndProcedure

Procedure fooArray(*value.AnyArray, Type, uBound)
  Protected i
  
  Select Type
    Case #PB_Integer
      For i = 0 To uBound
        Debug *value\i[i]
      Next
      
    Case #PB_Double
      For i = 0 To uBound
        Debug *value\d[i]
      Next
    Case #PB_String
      For i = 0 To uBound
        Debug "" + *value\c[i] + " - " + Chr(*value\c[i])
      Next
      
  EndSelect
  
EndProcedure

iVal.i = 100
dblVal.d = 99.1234

foo(@iVal, #PB_Integer)
foo(@dblVal, #PB_Double)

Dim iArray.i(10)
For i = 0 To 10
  iArray(i) = i + 100
Next

fooArray(@iArray(), #PB_Integer, ArraySize(iArray()))

sVal.s = "Hello World!"
fooArray(@sVal, #PB_String, Len(sVal) - 1)

Re: Basic Pointer Problem -- Pointer treated as simple varia

Posted: Wed Apr 29, 2020 1:04 pm
by mk-soft
String ByRef is a small problem ...

Link: https://www.purebasic.fr/english/viewto ... =3&t=74024

Solution

Code: Select all

;- TOP

Procedure foo(*pString.String) ; String ByRef need Pointer to Variable where storage the Pointer to String
  
  *pString\s = "**** " + *pString\s + " ****"
  
EndProcedure

Define sVal.String

sVal\s = "Hello World!"

foo(@sVal)

Debug sVal\s

; ----

; We need VarPtr

Macro VarPtr(_Var_, _Pointer_)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    lea rax, _Var_
    mov _Pointer_, rax
  CompilerElse
    lea eax, _Var_
    mov _Pointer_, eax
  CompilerEndIf  
  DisableASM
EndMacro


Global Text.s = "Hello World!"
Global *pText

VarPtr(Text, *pText) ; Get Pointer to Variable

foo(*pText)

Debug Text