|
Forum Index : Microcontroller and PC projects : Changed behaviour with STRUCTURES
| Author | Message | ||||
| disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 1094 |
This was discovered when implementing Structures on the CMM2. I confirmed the same behaviour on the latest Picomite 6.02.01b2. It only came to light when a previous unit test did not work as expected. It occurs when an array element e.g. b(3) from say the array b() is passed to a SUB that is expecting an array. (Not sure why you would want to do this). This has always been accepted and inside the SUB the original array is accessed By Reference, but inside the SUB there was an offset to the array index.(see note below). If STRUCTUREs are implemented this offset seems to be gone and passing b(3) or b() to the SUB is equivalent with no side affects. This post is just to note the change. ' --------- Prior to STRUCTURES ------------------------ ' When an array element e.g b(3) is passed to a SUB expecting an array ' it is accepted as an array, and treated as BYREF with no error/complaint. ' BUT the array inside the SUB is offset by the array element number provided. ' So pass b(3) and it ends up as b(0) inside the array in the SUB. ' Inside the SUB you cannot get to b(0),b(1) or b(2) ' If you maniplulate the array inside the SUB to write past its 256 byte ' boundary you can inadvertantly change the adjacent previous variable, ' if it happens to be the first variable then you write into a sensitive area ' and can kill MMBasic !!! ' This is not trapped as it is legal to work on the passed element as BYREF, ' you just need to behave and know its b(0) inside the SUB ! ' ' --- UPDATE when STRUCTURES are implemented. ------ ' This behaviour changes when STRUCTURES are implemented. ' byrefArrayShifted a,b(3),c ' byrefArrayShifted a,b(),c ' The two calls to SUB byrefArrayShiftedabove above. ' are both accepted and treated as passing the array b() ' and within the called SUB there is no offset to the array index. i.e. b(0) ' inside the SUB is b(0) of the calling code. Edited 2026-02-17 14:39 by disco4now F4 H7FotSF4xGT |
||||
| JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 4241 |
Sounds like a bug. John |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10963 |
If a subroutine is expecting an array and you pass it an array element then it is wrong and whatever behaviour you get shouldn't be relied on. |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 163 |
Yes, but if so, then the behavior from earlier. I completely agree with you! An array element is not the same as an array of elements! Even if both are passed by reference. The reference to the array contains not only the memory address of the array elements but also information about the array dimensions. Currently, you've probably solved this by simply (silently) ignoring the array index when the called SUB (or function) expects an array, and instead passing the entire original array. At least this way nothing bad can happen. If you wanted a "clean" solution, you'd have to teach MMBasic TypeCasts that perform type conversion "on the fly." Visual Basic has the CType operator (or the corresponding function) for this. https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/ctype-operator But I realize that this would be quite complex and also involve runtime and potentially memory usage, because temporary objects might have to be created on the stack and data copied, unless the variable management structure inherently contains a pointer to the actual memory location, which could then be set to the original data in the temporary variable instance. I would completely understand if you said, "I'm not going to bother with that right now." Regards, bfwolf |
||||
| ville56 Guru Joined: 08/06/2022 Location: AustriaPosts: 393 |
from my understanding this not really a case for typecasting. Typecasting, for me in the context of MMBasic would be converting from integer to float and vice versa if necessary. It is simply calling the SUB with wrong parameters(a single variable instead of an array), independently from the variable type. MMBasic could/should throw an error in this case. 73 de OE1HGA, Gerald |
||||
| Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 8560 |
Well, it *could* but isn't it a bit of an edge case really? You can't trap every error event and sometimes it probably isn't worth it. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10963 |
Sort of is. In C "x[0]" would give an error buy you could cast it to a pointer "&x[0]" which is the same as passing the array "x" UPDATE I've looked at this more and can easily make the code revert to the original behaviour OR through an error. The error route is the better solution but could break existing programs. thoughts? Edited 2026-02-17 21:39 by matherp |
||||
| JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 4241 |
I figured it was wanting/expecting an array slice. If it's not meant to be, no worries - a note in the manual or even better throw an error. I suppose in C, &x[3] and it would work fine (and there's an arguably uglier-looking expression, but let's not do too much C here) John Edited 2026-02-17 21:26 by JohnS |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 163 |
Of course, one could prevent any potential abuse and make the language "foolproof," but that would require endless checks at every turn and would significantly worsen performance. Typecasting, or type conversion, would, for example, convert an array into a subset of the array, or a single array element into an array of size 1 — if you wanted to enable that. But the effort required is considerable. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10963 |
UPDATE I've looked at this more and can easily make the code revert to the original behaviour OR throw an error. The error route is the better solution but could break existing programs. thoughts? |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 163 |
So, I think it would be possible to reverse this, but then it would have to be explicitly explained in the manual that when a single array element is passed to a subroutine/function that expects an array as an argument, it is implicitly converted to a reference to the array element, or more precisely, to an array starting at that index. The problem is: How does `BOUND(array()[,dimension])` behave within the subroutine or function? If it can return nonsensical values, this would have to be noted in the manual. The currently correct array boundaries could also be passed as an additional argument. Overall, this is of course dangerous without proper type conversion. ![]() Edited 2026-02-17 22:02 by bfwolf |
||||
| disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 1094 |
Peter, I think at one point we had it throwing an error when fine tuning the BYVAL/BYREF implementation but took it out so it matched the previous behaviour when not using the BYREF qualifier. Reverting to the original behaviour would make it consistent across all platforms. In all the years of MMBasic the only time I have seen it mentioned was when it came up when writing the unit tests for the BYREF/BYVAL implementation. Gerry Edited 2026-02-17 22:15 by disco4now F4 H7FotSF4xGT |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2026 |