Lbound/Ubound's dimension parameter

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Lbound/Ubound's dimension parameter

Post by dkl »

While I was working on getting lbound/ubound on fixed-size arrays evaluated at compile time it turned out that in order to get this we also need to decide how to handle an out-of-bounds dimension parameter.

Currently lbound/ubound will just crash if the specified dimension is drastically out of range, if it's only off-by-one or similar it can get "lucky" and return an undefined value instead of crashing (that's also sort of documented on the wiki). I think this must definitly be fixed by checking the value and at least returning a default value, i.e. 0, or showing an error. In case lbound/ubound are evaluated at compile-time, an error message can be shown easily, for the run-time case there should ideally be an -exx check, but that's a separate thing to work on, and returning 0 should be good enough when -exx was not used.

There also is one special case, if the value 0 is given as dimension, it is treated as if 1 was given. This was already noticed here. I believe this special case behaviour should be removed because it is useless.

Instead, how about using lbound/ubound( array, 0 ) to access the array's dimension count? It could work like this:

Code: Select all

lbound( array, 0 ) = 1-based index of first dimension = 1 (always)
ubound( array, 0 ) = 1-based index of last dimension = dimension count
I'm thinking this could be useful for at least two things:

Code: Select all

'' Look through all dimensions without knowing how many there are:
for d as integer = lbound( array, 0 ) to ubound( array, 0 )
    print "dimension " & d & ":", lbound( array, d ), "to", ubound( array, d )
next

Code: Select all

if( ubound( array, 0 ) = 0 ) then
    '' array is empty
end if
Any thoughts?
Gonzo
Posts: 722
Joined: Dec 11, 2005 22:46

Re: Lbound/Ubound's dimension parameter

Post by Gonzo »

Very useful, I agree..
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Lbound/Ubound's dimension parameter

Post by fxm »

This is perfect for me.
This allows to treat all cases of out-of-bounds dimension parameter, including for an un-sized dynamic array ('dim ... array()', or after 'erase array').
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

Re: Lbound/Ubound's dimension parameter

Post by gothon »

Excellent idea dkl! I was just thinking about this, there being no easy way to determine the number of dimensions allocated in a variable dimensional array.

I remember in VB6 you couldn't even determine if a dynamic array was empty or not without triggering a run time error, leading me to make this function.

Code: Select all

Public Function IsNoUBound(Arry) As Boolean
    Dim K As Long
    On Error GoTo NoUBound
    'IsNoUBound = False
    
    K = UBound(Arry)
    Exit Function
    
NoUBound:
    IsNoUBound = True
    Resume Next
End Function
Preferably an empty dynamic array would return -1 for the UBound like my VarArray macros do, but this will be a great improvement nonetheless.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Lbound/Ubound's dimension parameter

Post by counting_pine »

Arrays with multiple bounds might be nice to support officially.
Currently there are a couple of places in FB that fall short of this:
- There is a compile-time error that comes up when changing an array's dimensions in the scope where it is dimmed:

Code: Select all

dim a() as integer
redim a(0 to 9)
redim a(0 to 9, 0 to 9) '' error 36: Wrong number of dimensions
(It is OK for array parameters in functions though.)
- Runtime bounds checking will check the bounds but not the dimension count, so can falsely succeed on fewer dimensions:

Code: Select all

sub printa1(a() as integer, i as integer)
	print a(i)
end sub

redim a(0 to 2, 0 to 9) as integer

printa1(a(), 3) '' error
printa1(a(), 2) '' no error
(Note that it seems to match the first (only) parameter with the first bounds, while it would be slightly more "correct" to match the last (only) parameter with the last bounds.)
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Re: Lbound/Ubound's dimension parameter

Post by 1000101 »

To find out if there is an invalid dimension, lbound = 1, ubound = 0. I think this would be the simplest way to check at runtime but it would rely on the user checking.

ie:

Code: Select all

#Macro check( _arr_, _d_ )
   Print _d_;
   If( UBound( _arr_, _d_ ) >= LBound( _arr_, _d_ ) )Then
      Print " Is valid, ";
   Else
      Print " Is invalid, ";
   EndIf
   Print LBound( _arr_, _d_ ); "-"; UBound( _arr_, _d_ )
#EndMacro

Dim As Byte  some_array( 0 to 9, 3 to 17 )

check( some_array, 0 ) ' 0 Is Valid, 0 - 9
check( some_array, 1 ) ' 1 Is Valid, 3 - 17
check( some_array, 2 ) ' 2 Is Invalid, 1 - 0
The checks on the first two dimensions would return valid results (ubound >= lbound) but an invalid dimension (3rd) returns ubound < lbound (invalid).
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: Lbound/Ubound's dimension parameter

Post by dkl »

Ok, I have changed lbound/ubound accordingly. Now on to updating the wiki...
Post Reply