User Tools

Site Tools


re-dimensioning_20arrays

Re-dimensioning arrays

by Richard Russell, May 2014

BBC BASIC does not have a REDIM or REDIM PRESERVE statement, as found in some other dialects of BASIC (REDIM allows you to increase the dimensions of an existing array - the contents are lost - and REDIM PRESERVE allows you to increase the dimensions of an array without destroying its contents). However it is not difficult to provide an equivalent functionality using user-defined procedures (these are for BB4W, for BBCSDL see below):

        DEF PROCredim1d(RETURN P%,S%,D%)
        LOCAL A%
        IF ?P%<>1 ERROR 14, "Bad use of array"
        IF P%<LOMEM OR P%>HIMEM SYS "GlobalFree", P%
        SYS "GlobalAlloc", 64, 5+S%*(D%+1) TO A%
        IF A%=0 ERROR 11, "DIM space"
        ?A%=1 : A%!1=D%+1
        P% = A%
        ENDPROC
 
        DEF PROCredim2d(RETURN P%,S%,D%,E%)
        LOCAL A%
        IF ?P%<>2 ERROR 14, "Bad use of array"
        IF P%<LOMEM OR P%>HIMEM SYS "GlobalFree", P%
        SYS "GlobalAlloc", 64, 9+S%*(D%+1)*(E%+1) TO A%
        IF A%=0 ERROR 11, "DIM space"
        ?A%=2 : A%!1=D%+1 : A%!5=E%+1
        P% = A%
        ENDPROC
 
        DEF PROCredimpreserve1d(RETURN P%,S%,D%)
        LOCAL A%,N%,O%
        IF ?P%<>1 ERROR 14, "Bad use of array"
        N% = 5+S%*(D%+1)
        O% = 5+S%*P%!1
        SYS "GlobalAlloc", 64, N% TO A%
        IF A%=0 ERROR 11, "DIM space"
        IF N%>O% SWAP N%,O%
        SYS "RtlMoveMemory", A%, P%, N%
        A%!1=D%+1
        IF P%<LOMEM OR P%>HIMEM SYS "GlobalFree", P%
        P% = A%
        ENDPROC
 
        DEF PROCredimpreserve2d(RETURN P%,S%,D%,E%)
        LOCAL A%,N%,O%
        IF ?P%<>2 ERROR 14, "Bad use of array"
        N% = 9+S%*(D%+1)*(E%+1)
        O% = 9+S%*P%!1*P%!5
        SYS "GlobalAlloc", 64, N% TO A%
        IF A%=0 ERROR 11, "DIM space"
        IF N%>O% SWAP N%,O%
        SYS "RtlMoveMemory", A%, P%, N%
        A%!1=D%+1 : A%!5=E%+1
        IF P%<LOMEM OR P%>HIMEM SYS "GlobalFree", P%
        P% = A%
        ENDPROC

The above procedures support 1-dimensional and 2-dimensional arrays; equivalent routines for arrays with more dimensions can be derived if required. If you REDIM PRESERVE a 2-dimensional (or more) array you should normally only change the first dimension; if you change another dimension the data will be 'preserved' but will appear to have moved. Note that it isn't usually sensible to reduce the size of an array.

In each case the parameters to the procedure are the name of the array, the size of each element of the array (see table below) and the required dimension(s). As with the normal DIM statement, the available indices run from zero to the specified value.

Here is a simple demonstration program:

        DIM array(100)
        FOR I% = 0 TO 100
          array(I%) = SQR(I%)
        NEXT
        PROCredimpreserve1d(array(), ^array(1)-^array(0), 200)
        FOR I% = 101 TO 200
          array(I%) = SQR(I%)
        NEXT
        FOR I% = 0 TO 200
          IF array(I%) <> SQR(I%) STOP
        NEXT
        PRINT "Test completed successfully"
        END

Note that if you REDIM (not REDIM PRESERVE) a string array you must explicitly empty the array first:

        array$() = ""
        PROCredim1d(array$(), ^array$(1)-^array$(0), newsize%)

Here are equivalent procedures for BBC BASIC for SDL 2.0:

      DEF PROCredim1d(RETURN p%%,S%,D%)
      LOCAL a%%,N%
      IF ?p%%<>1 ERROR 14, "Bad use of array"
      N% = 5+S%*(D%+1)
      IF p%%<LOMEM OR p%%>HIMEM SYS "free", p%%
      SYS "malloc", N% TO a%%
      IF @platform% AND &40 ELSE a%%=!^a%%
      IF a%%=0 ERROR 11, "DIM space"
      SYS "memset", a%%, 0, N%
      ?a%%=1 : a%%!1=D%+1
      p%% = a%%
      ENDPROC
 
      DEF PROCredim2d(RETURN p%%,S%,D%,E%)
      LOCAL a%%,N%
      IF ?p%%<>2 ERROR 14, "Bad use of array"
      N% = 9+S%*(D%+1)*(E%+1)
      IF p%%<LOMEM OR p%%>HIMEM SYS "free", p%%
      SYS "malloc", N% TO a%%
      IF @platform% AND &40 ELSE a%%=!^a%%
      IF a%%=0 ERROR 11, "DIM space"
      SYS "memset", a%%, 0, N%
      ?a%%=2 : a%%!1=D%+1 : a%%!5=E%+1
      p%% = a%%
      ENDPROC
 
      DEF PROCredimpreserve1d(RETURN p%%,S%,D%)
      LOCAL a%%,N%,O%
      IF ?p%%<>1 ERROR 14, "Bad use of array"
      N% = 5+S%*(D%+1)
      O% = 5+S%*p%%!1
      SYS "malloc", N% TO a%%
      IF @platform% AND &40 ELSE a%%=!^a%%
      IF a%%=0 ERROR 11, "DIM space"
      IF N%>O% SWAP N%,O%
      SYS "memmove", a%%, p%%, N%
      a%%!1=D%+1
      IF p%%<LOMEM OR p%%>HIMEM SYS "free", p%%
      p%% = a%%
      ENDPROC
 
      DEF PROCredimpreserve2d(RETURN p%%,S%,D%,E%)
      LOCAL a%%,N%,O%
      IF ?p%%<>2 ERROR 14, "Bad use of array"
      N% = 9+S%*(D%+1)*(E%+1)
      O% = 9+S%*p%%!1*p%%!5
      SYS "malloc", N% TO a%%
      IF @platform% AND &40 ELSE a%%=!^a%%
      IF a%%=0 ERROR 11, "DIM space"
      IF N%>O% SWAP N%,O%
      SYS "memmove", a%%, p%%, N%
      a%%!1=D%+1 : a%%!5=E%+1
      IF p%%<LOMEM OR p%%>HIMEM SYS "free", p%%
      p%% = a%%
      ENDPROC

The most reliable way of determining the element size is to calculate it at run-time, as in the above examples, but for reference here are the appropriate sizes for each type of array:

byte e.g. array&()
size=1
32-bit integer e.g. array%()
size=4
40-bit float e.g. array()
size=5
string e.g. array$()
size=6
64-bit float e.g. array#()
size=8
string e.g. array$()
size=8*
64-bit integer e.g. array%%()
size=8*
80-bit float e.g. array()
size=10*

* BB4W version 6 or BBCSDL

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
re-dimensioning_20arrays.txt · Last modified: 2019/04/09 22:08 by richardrussell