Getting pointers from array

Blitz3D Forums/Blitz3D Beginners Area/Getting pointers from array

PowerPC603(Posted 2004) [#1]
I've got this testprogram:

Type Station
	Field Name$
	Field FileName$
	Field PosX%
	Field PosY%
	Field PosZ%
End Type

Dim ArrayStations.Station(15, 10)

For i = 1 To 15
	For j = 1 To 10
		ArrayStations(i, j) = New Station
	Next
Next

For i = 1 To 10
	Print ArrayStations(1, i)
Next

WaitKey()


But it gives an error on the line with the Print-command.

My intension was to have a different amount of (space)stations in each sector of space.
The first index-number (1-15) of the array is used as the sectornumber, the second one is used as the stationnumber.
One given sector may contain all 10 stations, where other sectors may contain only 1.

Since it is unneccessary to create ALL type-instances (which consumes memory if you have lots of fields), I only create a new type-instance when there's supposed to be a station in that sector (I read all data from txt-files, which works perfectly).

For looping through all stations in a specific sector, I thought I could check if the index of the array is bigger than "0".
If it is, do some stuff with the data of that type-instance.

I thought this would work, as a pointer is (AFAIK) just a memory-address, which is an integer.
This way I could check if a specific arrayindex held a value bigger than "0".
If it was bigger, than it would point to a type-instance and the station exists.

In this example, in sector 2 exists only 3 stations (not 10):
For i = 1 To 10
	If ArrayStations(2, i) <> 0 Then
		; do stuff here with the data of this type-instance
	EndIf
Next


But it doesn't work, as I get "Illegal type conversion error" on the IF-statement.

Now I bypassed this approach with some extra fields in another type (which existed also) and is used by another array, which hold the exact number of stations each sector contains.

Type Sector
	Field Name$
	Field StationsInSector%
End Type

Type Station
	Field Name$
	Field FileName$
	Field PosX%
	Field PosY%
	Field PosZ%
End Type

Dim ArraySectors.Sector(15)
Dim ArrayStations.Station(15, 10)

; Fill the sector-array with pointers to all sector-instances
For i = 1 To 15
	ArraySectors(i) = New Sector
Next

; some other routines come here to load data from txt-files, which also state
; the number of stations in each sector

; Only create type-instances for the number of stations in each sector which are needed
For i = 1 To 15
	For j = 1 To ArraySectors(i)\StationsInSector%
		ArrayStations(i, j) = New Station
	Next
Next

; Here are some routines which load data from the txt-file
; and put all values into the fields of the type-instances

; print the name of all stations in the galaxy
For i = 1 To 15
	For j = 1 To ArraySectors(i)\StationsInSector%
		Print ArrayStations(i, j)\Name$
	Next
Next

WaitKey()


In this last example, the program creates only the type-instances which are needed, to save some memory (unused type-instances are a total waste).
So if all sectors would have only 1 station in them, then only 1 secondary index (the second indexnumber) is a valid link to a type-instance.

Is there no other way of doing this?
I know I could loop through ALL Station-type-instances (which have a field which holds the name of the sector they are located in), but this would be too big/long.
As all routines in the game only need to know data about stuff in the sector where the player is located (cannot be in 2 or more sectors at once).


Who was John Galt?(Posted 2004) [#2]
Type Station
	Field Name$
	Field FileName$
	Field PosX%
	Field PosY%
	Field PosZ%
End Type

Dim ArrayStations.Station(15, 10)

For i = 1 To 15
	For j = 1 To 10
		ArrayStations(i, j) = New Station
		arraystations(i,j)\name=Mid$("abcdefghijklmnopqrst",j,1)
	Next
Next

For i = 1 To 10
	Print Handle(arraystations(1,i))
	Print ArrayStations(1, i)\name
Next

WaitKey()


Try the above which is almost identical to your original. To print the value of a type instance handle use handle(typevar).


big10p(Posted 2004) [#3]
You will get problems using Handle(). Say ArrayStation(1,5) doesn't contain a type pointer, then Handle(ArrayStation(1,5)) will cause an error.

[edit] Actually, this won't cause an error. It just returns 0. Oh, well. Take your pick :) [edit]

Instead, just explicitly cast the type pointer to an int before comparing it to zero to see if it's a valid pointer:
Type Station
	Field Name$
	Field FileName$
	Field PosX%
	Field PosY%
	Field PosZ%
End Type

Dim ArrayStations.Station(15, 10)

For i = 1 To 15
	For j = 1 To Rand(0,10)
		ArrayStations(i, j) = New Station
		arraystations(i,j)\name=Mid$("abcdefghijklmnopqrst",j,1)
	Next
Next


For i = 1 To 15
	For j = 1 To 10
		ptr = Int(arraystations(i,j))
		If ptr Then Print ptr + " " + ArrayStations(i,j)\name
	Next
Next

WaitKey()


TBH, I was surprised this worked as I'm sure I tried something similar in the past. Seems to work fine, though. I must be thinking of something else. :)


Perturbatio(Posted 2004) [#4]
An alternative:
Type Station
	Field Name$
	Field FileName$
	Field PosX%
	Field PosY%
	Field PosZ%
End Type

Dim ArrayStations.Station(15, 10)

For i = 1 To 15
	For j = 1 To 10

		ArrayStations(i, j) = New Station
	Next
Next

For i = 1 To 10
	Print Str(ArrayStations(1, i))
Next

WaitKey()
End



Floyd(Posted 2004) [#5]
The correct way to see if a Type object exists is by comparing to Null.
Casting to an integer and comparing to zero is not reliable.
Type T
	Field n
End Type

Dim a.T( 5 )
a(4) = New T

For i = 0 To 5
	If a(i) <> Null Then Print "Element " + i + " exists."
	If Int( a(i) ) <> 0 Then Print "Pointer a(" + i + ") is non-zero."
Next

Print

Delete a(4)

For i = 0 To 5
	If a(i) <> Null Then Print "Element " + i + " exists."
	If Int( a(i) ) <> 0 Then Print "Pointer a(" + i + ") is non-zero."
Next

WaitKey : End



PowerPC603(Posted 2004) [#6]
Thanks all, I can really use those things, especially the comparison with Null, didn't know about that yet.

But as you stated, Floyd, the comparison with Int(...) will also work, as long as the type-instance exists and wasn't created before (checked that with commenting the line "a(4) = New T").

For my game, both ways will work the same (Int and Null), because the type-instances are created when loading data and are only destroyed (or deleted) when the game quits.
The game needs all data in memory (which speeds up loading times between sector-jumps).
When the game is running, no type-instance is deleted (for stations, sectors, asteroids, jumpgates and many more stuff in space (except spaceships I think, I'm not that far yet).

If I get it right, the comparison to Null actually checks if the pointer (that's stored in the array) in valid (points to a existing type-instance) and the Int-comparison just compares the integer-value of that pointer with 0 (and doesn't check if that pointer is a valid one).

Is this correct?

Or is it just that an empty array-index holds the value Null instead of "0" (in case of an array which holds pointers)?


big10p(Posted 2004) [#7]
God, I feel like such a numpty! :) Of course a comparison to Null is the right way to do it. I think I got suduced by the original code that needed to actually print the pointer. Well, that's my excuse and I'm sticking to it! :P

If I get it right, the comparison to Null actually checks if the pointer (that's stored in the array) in valid (points to a existing type-instance) and the Int-comparison just compares the integer-value of that pointer with 0 (and doesn't check if that pointer is a valid one).

Is this correct?


Yes, from Floyd's code, this does indeed seem to be the case. This surprised me as I had no idea a comparison to Null in Blitz worked like this. It's been a while but I'm sure a comparison to NULL in C/C++ isn't this helpful. Thanks for the tip, Floyd! ;)