TYPE, and redim array in them

New to FreeBASIC? Post your questions here.
~EXIS~
Posts: 21
Joined: Sep 01, 2006 18:57
Location: RUSSIA

TYPE, and redim array in them

Post by ~EXIS~ »

Im write the code
Type aaa
b(0) As integer
End Type

Dim a As aaa

ReDim a.b(0 To 10)
But compiler write
Build error(s)
C:\Program Files\FreeBASIC\fbc -s gui "(Untitled).bas"
(Untitled).bas(7) error 59: Expected array, a in 'ReDim a.b(0 To 10)'
Why? What mistake im do?
dani.user
Posts: 284
Joined: Sep 30, 2006 10:41

Post by dani.user »

Variable size arrays in types are currently not supported. Use pointers instead
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Post by KristopherWindsor »

See also: VB like types. ;-)
~EXIS~
Posts: 21
Joined: Sep 01, 2006 18:57
Location: RUSSIA

Post by ~EXIS~ »

v1ctor
Site Admin
Posts: 3804
Joined: May 27, 2005 8:08
Location: SP / Bra[s]il
Contact:

Post by v1ctor »

It can also be implemented with properties (the good is that you don't ever need to REDIM it, the bad is that it supports only one dimension):

Code: Select all

Type foo
	declare property bar( index as integer, value as integer )
	declare property bar( index as integer ) as integer 
	declare destructor ( )
	
 private:
	array as integer ptr = 0
	elements as integer = 0
	declare sub redim_me( index as integer )
End Type 

'':::::
sub foo.redim_me( index as integer )
	if( index >= elements ) then
		elements = index
		array = reallocate( array, elements * len( integer ) )
	end if	
end sub

'':::::
property foo.bar( index as integer, value as integer )
	if( index < 0 ) then
		error 1
		return
	end if
		
	redim_me( index )
	array[index] = value
end property

'':::::
property foo.bar( index as integer ) as integer 
	if( index < 0 ) then
		error 1
		return 0
	end if

	redim_me( index )
	return array[index]
end property

'':::::
destructor foo ( )
	if( array <> 0 ) then
		deallocate array
		array = 0
	end if
end destructor

'':::::
	dim f as foo

	f.bar( 5 ) = 1234
	
	print f.bar( 5 )
~EXIS~
Posts: 21
Joined: Sep 01, 2006 18:57
Location: RUSSIA

Post by ~EXIS~ »

Thanks a lot, for ideas. I'm hope this feature be added in next relases of compilator.
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Post by badidea »

Bummer, first time I see a use for redim instead of using pointers, turns out it does not work:

Code: Select all

type some_type
  as integer array(0, 0)
  as integer numX, numY
  declare sub init(initNumX as integer, initNumY as integer)
  declare sub show()
end type

sub some_type.init(initNumX as integer, initNumY as integer)
  dim as integer xi, yi
  numX = initNumX
  numY = initNumY
  redim array(numX, numY)
  for yi = 0 to numY-1
    for xi = 0 to numX-1
      array(xi, yi) = 1
    next
  next
end sub

sub some_type.show()
  dim as integer xi, yi
  for yi = 0 to numY-1
    for xi = 0 to numX-1
      print array(xi, yi);
    next
  next
end sub

dim as some_type x

x.init(10, 10)
x.show()
sleep
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Post by stylin »

Hi badidea, it can be a bit confusing. At the moment an array member acts like a fixed-length string member (as opposed to a variable-length string member), its elements are stored as part of the object and contribute to its size (so resizing wouldn't make sense even if it did somehow "work").

edit: you can simulate that behavior in C/C++, but that's for dynamically allocated objects where the array member is the last member and memory is managed manually. I don't know if the same technique would work in FreeBASIC, but certainly not for objects allocated on the stack.
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Post by badidea »

I understand. Guess I need to convert my code to use pointers and pointers to pointers for 2d data. Like in the example on the wiki:

Code: Select all

'Create 10 rows of integer pointers
myMemArray = CAllocate(10, SizeOf(Integer Ptr))
'Add 10 columns of integers to each row
For i = 0 To 9
 myMemArray[i] = CAllocate(10, SizeOf(Integer))
Next
'Add some data to the memory segment
For i = 0 To 9
 For j = 0 To 9
  myMemArray[i][j] = Int(Rnd * 10)
 Next
Next
'Free memory segment
For i = 0 To 9
 Deallocate myMemArray[i]
Next
'Free the pointer to pointer
Deallocate myMemArray
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Post by stylin »

Yeah, or perhaps,

Code: Select all

'Create 10 rows of integer pointers
var myMemArray = new integer ptr[10]

'Add 10 columns of integers to each row
for i as integer = 0 to 9
    myMemArray[i] = new integer[10]
next

'Add some data to the memory segment
for i as integer = 0 to 9
    for j as integer = 0 to 9
        myMemArray[i][j] = int(rnd * 10)
    next
next

'Free memory segment
for i as integer = 0 to 9
    delete[] myMemArray[i]
next

'Free the pointer to pointer
delete[] myMemArray
fxm
Moderator
Posts: 12158
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Post by fxm »

badidea wrote:Bummer, first time I see a use for redim instead of using pointers, turns out it does not work:

Code: Select all

type some_type
  as integer array(0, 0)
  as integer numX, numY
  declare sub init(initNumX as integer, initNumY as integer)
  declare sub show()
end type

sub some_type.init(initNumX as integer, initNumY as integer)
  dim as integer xi, yi
  numX = initNumX
  numY = initNumY
  redim array(numX, numY)
  for yi = 0 to numY-1
    for xi = 0 to numX-1
      array(xi, yi) = 1
    next
  next
end sub

sub some_type.show()
  dim as integer xi, yi
  for yi = 0 to numY-1
    for xi = 0 to numX-1
      print array(xi, yi);
    next
  next
end sub

dim as some_type x

x.init(10, 10)
x.show()
sleep
IMHO, in the procedure 'some_type.init', the line 'redim array(numX, numY)' creates a new local array (in the stack):
- You can verify that, replacing 'redim array(numX, numY)' by 'redim this.array(numX, numY)', and obtaining the compilation error : error 59: Expected array, this in 'redim this.array(numX, numY)'.
- Another way to verify this local array creation (in the stack) is to insert at the beginning of the procedure 'some_type.show' the line 'redim preserve array(numX, numY)' and to observe that all displayed values are equal to 0, despite the keyword "preserve" (new local array initiation in the stack).


Very important in my opinion (as compiling at least once with the option -exx):
  • Me, in any procedure member, I used to always explicitly address the members names with the prefix:
    - 'This.' for non static member name,
    - 'Typename.' for static member name,
    - '.' for duplicated name (with one member) out of UDT,
    in order to avoid conflicts between names.
  • With this, such behavior can not happen so, because of detected compilation error.
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Post by badidea »

Tried to make some 2d allocation & deallocation routines:

Code: Select all

function alloc2d(d1size as integer, d2size as integer, varSize as integer) as any ptr ptr
  dim as any ptr ptr array
  dim as integer i
  array = allocate(d1size * sizeof(any ptr))
  for i = 0 to d1size-1
    array[i] = allocate(d2size * varSize)
  next
  return array
end function

sub free2d(array as any ptr ptr, d1size as integer)
  dim as integer i
  for i = 0 to d1size-1
    deallocate(array[i])
  next
  deallocate(array)
end sub

dim as integer d1, d2, i1, i2
dim as integer ptr ptr ppInt
dim as double ptr ptr ppDbl

d1 = 10: d2 = 5
ppInt = alloc2d(d1, d2, sizeof(integer))
ppDbl = alloc2d(d1, d2, sizeof(double))

for i1 = 0 to d1-1
  for i2 = 0 to d2-1
    ppInt[i1][i2] = 1
    ppDbl[i1][i2] = 1.0
  next
next

free2d(ppInt, d1)
free2d(ppDbl, d1)

print "End."
sleep
Unfortunately, the free2d (deallocation) routine needs to be told the size of the first dimension.
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Post by stylin »

badidea, nice codes. Sometimes an allocator will allocate a little more memory at the beginning of the array for housekeeping info (sizes, ptrs to internal memory blocks, etc.) and simply return the address of the user data immediately following this housekeeping info. May be something to look into if you don't want to keep track of dimension sizes.
matwachich
Posts: 70
Joined: Jun 11, 2011 3:36

Post by matwachich »

Why this code bugs??? (Modified from the 2nd post)

Code: Select all

Type foo
        declare property bar( index as integer, value as integer )
        declare property bar( index as integer ) as integer
        declare destructor ( )
       
 private:
        array as integer ptr = 0
        elements as integer = 0
        declare sub redim_me( index as integer )
End Type

'':::::
sub foo.redim_me( index as integer )
        if( index >= elements ) then
                elements = index
                array = reallocate( array, elements * len( integer ) )
        end if       
end sub

'':::::
property foo.bar( index as integer, value as integer )
        if( index < 0 ) then
                error 1
                return
        end if
               
        redim_me( index )
        array[index] = value
end property

'':::::
property foo.bar( index as integer ) as integer
        if( index < 0 ) then
                error 1
                return 0
        end if

        redim_me( index )
        return array[index]
end property

'':::::
destructor foo ( )
        if( array <> 0 ) then
                deallocate array
                array = 0
        end if
end destructor

'':::::
        dim f as foo

        f.bar( 1 ) = 10
        f.bar( 3 ) = 30
        f.bar( 5 ) = 50
       
        print f.bar( 1 )
        print f.bar( 3 )
        print f.bar( 5 )
        
        Sleep
fxm
Moderator
Posts: 12158
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Post by fxm »

This line must be modified in sub foo.redim_me( index as integer ):
array = reallocate( array, ( elements + 1 ) * len( integer ) )

because in fact, 'elements' represents the UBound of the array (max_index), and you must allocate max_index + 1 integers, in order to cover the interval [0 , max_index].
Post Reply