Unexpected structure behaviour

Here you can link to screenshots and demos etc. of programs made using BBC BASIC
tpegc
Posts: 3
Joined: Tue 24 Apr 2018, 16:28

Unexpected structure behaviour

Post by tpegc »

Hello - apologies if this is the wrong place, or badly posted - newbie alert!

First off thank you to Richard Russell for creating and maintaining BBC Basic for Windows and SDL. I went from ZX80 Basic to BBC Micro Basic to university FORTRAN and then into a plethora of languages across my career, and it is with great joy that I return to BBC Basic for pure fun now.

I have been playing with structures and found some unexpected behaviour. The following code should only change one array structure per dump, but it modifies others where indicated. It is entirely possible that I am being stupid - if so apologies again - but any explanation would be very welcome

Code: Select all

      MODE 14

      DIM a{t,s$}
      DIM array{(4)}=a{}
      FORi=0TO4
        array{(i)}.t=-1
        array{(i)}.s$="null"
      NEXT
      PROCdump

      PROCset(a{},0,"Zero?")
      array{(0)}=a{}
      PROCdump

      PROCset(a{},1,"11")
      array{(1)}=a{}
      PROCdump

      PROCset(a{},2,"222")
      array{(2)}=a{} : REM unexpected, array{(1)}.s$="22"
      PROCdump

      PROCset(a{},3,"3333")
      array{(3)}=a{} : REM unexpected, array{(0)}.s$="3333?"
      PROCdump

      array{(4)}.t=4.4
      array{(4)}.s$="Four.four"
      PROCdump

      a{}.t=4
      a{}.s$="44444"
      array{(4)}=a{} : REM unexpected, array{(3)}.s$="4444"
      PROCdump

      END

      DEFPROCdump:LOCALi
      FORi=0TO4
        PRINT"dataitem ";i;", t=";array{(i)}.t;" s$=""";array{(i)}.s$;""""
      NEXT
      PRINT
      ENDPROC

      DEFPROCset(RETURN struc{},p,q$)
      struc{}.t=p
      struc{}.s$=q$
      ENDPROC
tpegc
Posts: 3
Joined: Tue 24 Apr 2018, 16:28

Re: Unexpected structure behaviour

Post by tpegc »

I definitely should have said - this is BBC Basic for SDL 2.0, with identical behavior in BB4W v6.16a
Richard Russell
Posts: 704
Joined: Tue 18 Jun 2024, 09:32

Re: Unexpected structure behaviour

Post by Richard Russell »

tpegc wrote: Wed 15 Jul 2026, 13:45 I have been playing with structures and found some unexpected behaviour.

Code: Select all

      array{(0)}=a{}
From the manual "Do not copy structures containing string members; since only the string descriptor is copied, not the string itself, you are likely to confuse BASIC and may even crash it".

Since you are doing something specifically forbidden, the behaviour may be 'surprising' but it's not "unexpected"! :lol:
tpegc
Posts: 3
Joined: Tue 24 Apr 2018, 16:28

Re: Unexpected structure behaviour

Post by tpegc »

:oops: I really should have read the entire section on structures, not just the first bit and then assumed they would work how I wanted them to!

Thank you for the super quick and, in the circumstances, very gentle correction of my stupidity :D
Richard Russell
Posts: 704
Joined: Tue 18 Jun 2024, 09:32

Re: Unexpected structure behaviour

Post by Richard Russell »

tpegc wrote: Thu 16 Jul 2026, 10:05 Thank you for the super quick and, in the circumstances, very gentle correction of my stupidity :D
Absolutely not "stupidity". Indeed assuming that something will work in the way that it looks as if it ought to work - and furthermore runs without reporting an error - is entirely reasonable.

It's largely for implementation convenience, as well as speed, that all the 'vector copy' operations simply check that the types and sizes are compatible, then do a straight memcpy-style copy from source to destination. This works fine for everything except structures containing 'moveable' strings.

As for workarounds, there are two main approaches that you could consider. Firstly, use 'fixed' (NUL-terminated) strings rather than 'moveable' strings in the structure (here with a maximum length of 255 bytes):

Code: Select all

      MODE 20

      DIM a{t,s&(255)}
      DIM array{(4)}=a{}
      FORi=0TO4
        array{(i)}.t=-1
        array{(i)}.s&()="null"
      NEXT
      PROCdump

      PROCset(a{},0,"Zero?")
      array{(0)}=a{}
      PROCdump

      PROCset(a{},1,"11")
      array{(1)}=a{}
      PROCdump

      PROCset(a{},2,"222")
      array{(2)}=a{}
      PROCdump

      PROCset(a{},3,"3333")
      array{(3)}=a{}
      PROCdump

      array{(4)}.t=4.4
      array{(4)}.s&()="Four.four"
      PROCdump

      a{}.t=4
      a{}.s&()="44444"
      array{(4)}=a{} 
      PROCdump

      END

      DEFPROCdump:LOCALi
      FORi=0TO4
        PRINT"dataitem ";i;", t=";array{(i)}.t;" s&()=""";array{(i)}.s&();""""
      NEXT
      PRINT
      ENDPROC

      DEFPROCset(RETURN struc{},p,q$)
      struc{}.t=p
      struc{}.s&()=q$
      ENDPROC
Secondly, write a 'structure copy' procedure that actually does the right thing:

Code: Select all

      MODE 20

      DIM a{t,s$}
      DIM array{(4)}=a{}
      FORi=0TO4
        array{(i)}.t=-1
        array{(i)}.s$="null"
      NEXT
      PROCdump

      PROCset(a{},0,"Zero?")
      PROCcopy(array{(0)},a{})
      PROCdump

      PROCset(a{},1,"11")
      PROCcopy(array{(1)},a{})
      PROCdump

      PROCset(a{},2,"222")
      PROCcopy(array{(2)},a{})
      PROCdump

      PROCset(a{},3,"3333")
      PROCcopy(array{(3)},a{})
      PROCdump

      array{(4)}.t=4.4
      array{(4)}.s$="Four.four"
      PROCdump

      a{}.t=4
      a{}.s$="44444"
      PROCcopy(array{(4)},a{})
      PROCdump

      END

      DEFPROCdump:LOCALi
      FORi=0TO4
        PRINT"dataitem ";i;", t=";array{(i)}.t;" s$=""";array{(i)}.s$;""""
      NEXT
      PRINT
      ENDPROC

      DEFPROCset(struc{},p,q$)
      struc{}.t=p
      struc{}.s$=q$
      ENDPROC

      DEF PROCcopy(dst{},src{})
      dst.s$=""
      dst{}=src{}
      ]^dst.s$=0
      dst.s$=src.s$
      ENDPROC