Page 1 of 1

Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 7:00 am
by skape
Hello,

I'm playing around with pointers, lists, and "constructing" procedures. Here is my test code:

Code: Select all

Structure WALKER
  x.f
  y.f
EndStructure

Procedure Walker_new(x.f, y.f)
  *w.WALKER = AllocateMemory(SizeOf(WALKER))
  *w\x = x
  *w\y = y
  ProcedureReturn *w
EndProcedure

Procedure Walker_move(*w.WALKER)
  Select Random(3)
    Case 0
      *w\x + 1
    Case 1
      *w\x - 1
    Case 2
      *w\y + 1
    Case 3
      *w\y - 1
  EndSelect
EndProcedure

Procedure Walker_draw(*w.WALKER)
  FrontColor(RGB(255,255,255))
  Plot(*w\x, *w\y)
EndProcedure


; -----------------------------------------------------------------------
;- Open window
If Not InitSprite() | InitKeyboard()
  MessageRequester("Error", "Initialization error.", #PB_MessageRequester_Ok)
  End
EndIf

If Not OpenWindow(0, 100, 100, 640, 340, "Random Walker", #PB_Window_ScreenCentered|#PB_Window_TitleBar|#PB_Window_SystemMenu)
  MessageRequester("Error", "Error opening window.", #PB_MessageRequester_Ok)
  End
EndIf

If Not OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0))
  MessageRequester("Error", "Error opening window.", #PB_MessageRequester_Ok)
  End
EndIf


NewList *ws.WALKER()
AddElement(*ws())
*ws() = Walker_new(ScreenWidth()/2,ScreenHeight()/2)
AddElement(*ws())
*ws() = Walker_new(ScreenWidth()/3,ScreenHeight()/2)
AddElement(*ws())
*ws() = Walker_new(ScreenWidth()*2/3,ScreenHeight()/2)

w.WALKER
w\x = 5
w\y = 10

Walker_move(@w)

;- Start loop
ClearScreen(RGB(255,255,255))
CreateSprite(0,ScreenWidth(),ScreenHeight())

Repeat
  ; Process window events
  Repeat
    Event = WindowEvent()
    
    Select (Event)
      Case #PB_Event_CloseWindow
        End
    EndSelect
  Until Event = 0
  
  ; Process keyboard
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Escape)
    PostEvent(#PB_Event_CloseWindow)
  EndIf
  
  
  ; Simulation
  ForEach *ws()
    Walker_move(*ws())
  Next

  ; Drawing to sprite before display
  StartDrawing(SpriteOutput(0))
    ForEach *ws()
      Walker_draw(*ws())
    Next
  StopDrawing()
    
  DisplaySprite(0,0,0)
  
  FlipBuffers()
  
ForEver 
1) I am wondering: if I have a procedure that takes a pointer as a parameter, and then I try to pass in a variable of that structure type, it works. Does PB automatically pass the parameter as a pointer, even though I created the variable non-dynamically? It seems to make no difference if I just pass the variable (w) or the address (@w). What's going on here?

2) Is that a good way to make a list of pointers (*ws())? Does this code make sense?

3) I am drawing to a sprite and then drawing this to the screen. Is this an efficient way to use the 2D Drawing commands on Mac? I seemed to get "interesting" results drawing to the screen (ScreenOutput()) directly, without clearing the backbuffer using ClearScreen(). Is this a good way of doing 2D drawing, not using sprites?

(And yes, I realize I am needlessly looping through my list twice... ;) )

Thanks! :)

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 8:15 am
by Demivec
skape wrote:1) I am wondering: if I have a procedure that takes a pointer as a parameter, and then I try to pass in a variable of that structure type, it works. Does PB automatically pass the parameter as a pointer, even though I created the variable non-dynamically? It seems to make no difference if I just pass the variable (w) or the address (@w). What's going on here?
Whenever a structured variable is passed as a parameter PureBasic will pass the address of the structure only. This means that you currently don't have to use the '@' operator when you do this. It is arguably a good idea to always use it so that you are clear what is going on (or for other's benefit who may read your code), though I personally will not use it in this particular case.
skape wrote:2) Is that a good way to make a list of pointers (*ws())? Does this code make sense?
It seems to work just fine. Yes the code makes sense.

One small note though, when you delete an element from the list *ws() you will need to free the memory that element is pointing to, as it won't be done automatically except at the end of the program.

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 8:27 am
by netmaestro
With var.struct, var and @var may be used interchangeably but @var is probably superior as it's reminding the person who might be skimming over the code later that it's an address. It's just a bit more self-documenting. Note that none of the above applies to *var.struct = AllocateMemory(SizeOf(struct)). Here *var holds the address in memory of the beginning of the structured data while @*var provides the address of the *var pointer in memory, a very different thing. So for structured variables, @var = var but for structured pointers, @*var <> *var.

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:04 pm
by skape
Thank you Demivec and netmaestro! :)

Anyone have any comments on the graphics techniques (Problem 3)?

Also, what exactly is AllocateStructure()? Is it essentially AllocateMemory(SizeOf(STRUCTURE))?

Thanks for your help! :)

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:33 pm
by luis
skape wrote: Also, what exactly is AllocateStructure()? Is it essentially AllocateMemory(SizeOf(STRUCTURE))?
No. It's more like *ptr.STRUCTURE = AllocateMemory(SizeOf(STRUCTURE)) plus InitializeStructure(*ptr, STRUCTURE)

It's in the help:
help wrote: Allocates a new dynamic structure item. This dynamic structure item is properly initialized and ready to use, without the need to call InitializeStructure(). To access the structure data, a pointer associated with the specified 'StructureName' has to be used.
You need to initialize a dynamically allocated structure if it contains Arrays, Lists or Maps as fields. You don't need to do so for a structure allocated on the stack like Protected MyStruct.STRUCTURE since the compiler do that automatically in that case.

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:42 pm
by skape
Thanks luis. :)

So, if I don't need my structure initialized (automatically, as I am doing it manually in my "constructor"), would it essentially be a slightly slower (but slightly shorter code) AllocateMemory(SizeOf(STRUCTURE))? Also it would have the benefit of zeroing or initializing all of the structured memory?

EDIT:
Gotcha. So it would not be a bad idea to allocate all dynamic structure pointers that way?

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:47 pm
by luis
I reply anyway :wink:

Yes, if you don't need the structure to be initialized you can use AllocateMemory() if you prefer and yes the memory will be filled with zero (by default).
So it would not be a bad idea to allocate all structure pointers that way?
Ehm, sorry I'm not sure anymore what "that way" is. Can you rephrase ?

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:52 pm
by skape
Ehm, sorry I'm not sure anymore what "that way" is. Can you rephrase ?
Ha, yes, sorry! :)

I mean using AllocateStructure() is not a bad idea for dynamic structures, just to make sure EVERYTHING is initialized. I could see that being important for a more complex structure.

Re: Pointers in Lists and Structure Parameters (from a noob)

Posted: Sun Feb 01, 2015 3:56 pm
by luis
Yes, I don't see any problem with that AFAIK.