Basic Pointer Problem -- Pointer treated as simple variable

Just starting out? Need help? Post your questions and find answers here.
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Basic Pointer Problem -- Pointer treated as simple variable

Post 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
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

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

Post 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.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post 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
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

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

Post 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
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

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

Post 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
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

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

Post 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.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

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

Post 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)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

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

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply