Posts: 250
Threads: 44
Joined: May 2022
Reputation:
28
Code: (Select All) Type snd1
l As Integer
r As Integer
End Type
Type snd2
l As _Unsigned _Byte
r As _Unsigned _Byte
End Type
ReDim s(0) As snd2 '1
ReDim s(0) As snd1 '2
Print Len(s(0).l) 'expected is 2
Is there any way to fix this, or does that mean I have to completely rewrite 90 percent of the program that relied on this?
Posts: 250
Threads: 44
Joined: May 2022
Reputation:
28
Maybe it will be related to some medieval definition from qbasic.... (I'm assuming that you can't do for example DIM L as INTEGER and then DIM L as LONG, an error will occur - the variable is already used, so this will probably be the same case, but there is a lack of error catching in the IDE. (that's a guess). I will this ancient limitation bypass via MEM.
Posts: 2,700
Threads: 327
Joined: Apr 2022
Reputation:
217
Honestly, this shouldn't even be possible. You should get an Invalid Type error, but it's not catching it in this case.
DIM s(0) AS INTEGER
DIM s(0) AS _UNSIGNED _BYTE
The above should error out for you with an Invalid Type or Duplicate Definition or similar error. Why it's not tossing that same style error for a UDT needs to be looked into.
Posts: 3,981
Threads: 177
Joined: Apr 2022
Reputation:
220
04-23-2023, 02:22 PM
(This post was last modified: 04-23-2023, 02:25 PM by bplus.)
Gotta say it looks like a bug!
Further test reveals it does accept an integer argument as integer:
Code: (Select All) Type snd1
l As Integer
r As Integer
End Type
Type snd2
l As _Unsigned _Byte
r As _Unsigned _Byte
End Type
ReDim s(0) As snd2 '1
Print Len(s(0).l) 'expected is 1
' !!!! is there a way to clear a varaible from memory right here???
ReDim s(0) As snd1 '2
Print Len(s(0).l) 'expected is 2
s(0).l = 55
Print s(0).l ' expect 55 OK
Print Len(s(0).l) 'expect 2 what?
If the first s(0) could be cleared from memory when s(0) was REDIM'd, Len() might get it's facts straight.
Are there 2 s(0)'s such that Len() gets the first one set up in variable table?
b = b + ...
Posts: 3,981
Threads: 177
Joined: Apr 2022
Reputation:
220
Look what happens when try to REDIM s(0) as a normal variable:
Code: (Select All) Type snd1
l As Integer
r As Integer
End Type
Type snd2
l As _Unsigned _Byte
r As _Unsigned _Byte
End Type
ReDim s(0) As snd2 '1
Print Len(s(0).l) 'expected is 1
' !!!! is there a way to clear a varaible from memory right here???
redim as long s(0) ' <<<<<<<<<<<< red lined !!!
ReDim s(0) As snd1 '2 ' so this should not be legal either
'_Delay .1 'wait to clear first instance of s(0)
Print Len(s(0).l) 'expected is 2
s(0).l = 55
Print s(0).l ' expect 55 OK
Print Len(s(0).l) 'expect 2 what?
b = b + ...
Posts: 250
Threads: 44
Joined: May 2022
Reputation:
28
@BPlus
This is the same as what I write about above, 55 will remain there because it is in the range for the _Unsigned _Byte type. Once the field is defined as an unsigned byte, it simply stays that way forever. LEN for _Unsigned _Byte is 1 (lenght is 1 byte) To confirm, insert the number 355 instead of 55, the Unsigned Byte data type will overflow and PRINT will print 355 - 255 = 99 (because even zero is taken into account) and LEN return variable LENGHT (byte - size), not variable value, so this can not be deleted.
Posts: 3,981
Threads: 177
Joined: Apr 2022
Reputation:
220
04-23-2023, 03:49 PM
(This post was last modified: 04-23-2023, 03:59 PM by bplus.)
(04-23-2023, 03:31 PM)Petr Wrote: @BPlus
This is the same as what I write about above, 55 will remain there because it is in the range for the _Unsigned _Byte type. Once the field is defined as an unsigned byte, it simply stays that way forever. LEN for _Unsigned _Byte is 1 (lenght is 1 byte) To confirm, insert the number 355 instead of 55, the Unsigned Byte data type will overflow and PRINT will print 355 - 255 = 99 (because even zero is taken into account) and LEN return variable LENGHT (byte - size), not variable value, so this can not be deleted.
Oh right! sorry don't use Byte that much, thanks for reminder.
Still isn't interesting you can REDIM an UDT of same name but not a regular variable.
Another example:
Code: (Select All) ReDim x As Integer
x = 2
redim x as long ' red lined!
You shouldn't be allowed to REDIM the 2nd s(0) as a different type than original, if you wish consistency to rule in your PL, not a great rule for Basic though ;-))
b = b + ...
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
(04-23-2023, 11:57 AM)Petr Wrote: Code: (Select All) Type snd1
l As Integer
r As Integer
End Type
Type snd2
l As _Unsigned _Byte
r As _Unsigned _Byte
End Type
ReDim s(0) As snd2 '1
ReDim s(0) As snd1 '2
Print Len(s(0).l) 'expected is 2
Are you trying to do an "union" type like in C? :O
Why are you trying to redimension the same array only to change the types of the same fields?
Maybe you already know but you have to use _MEM on a variable which is more than one byte in size, and you need to extract it byte by byte or something else. OK I saw the second post here...
Be glad that "Integer" will always be 2 bytes in anything directly compatible with QuickBASIC and QBasic. Because in Freebasic they decided to throw it out of whack. For that language many programs for QBasic would have to be rewritten to change from "As Integer" to "As Short" if the programmer really meant 2-byte integer.
Posts: 3,981
Threads: 177
Joined: Apr 2022
Reputation:
220
@mnrvovrfc I think he wants to use same code on 2 different Types of UDT. Lazy or smart? if you can get away with it, smart! otherwise, stupid and have to rewrite everything involving those UDTs.
b = b + ...
Posts: 2,700
Threads: 327
Joined: Apr 2022
Reputation:
217
04-23-2023, 06:15 PM
(This post was last modified: 04-23-2023, 06:18 PM by SMcNeill.)
I've did sometime similar in the past with CustomType Self-Refrencing libraries:
Code: (Select All) DECLARE CUSTOMTYPE LIBRARY 'Use Customtype for self-referencing a sub written inside your program
SUB SUB_EXAMPLE (BYVAL passed AS _OFFSET) 'this points to SUB EXAMPLE below, but uses an OFFSET to point to its parameter.
'NOTE: The sub/function name *MUST* be the same as QB64 translates it as, for us.
'General rule of thumb is to make the subname ALL CAPS, preceeded by SUB_ or FUNCTION_ as dictated.
SUB SUB_EXAMPLE2 (BYVAL passed AS _OFFSET)
END DECLARE
TYPE DataType 'A datatype to use as an example
x AS STRING * 12
y AS LONG
z AS LONG
END TYPE
TYPE DataType2 'a second datatype
byte1 AS _UNSIGNED _BYTE
byte2 AS _UNSIGNED _BYTE
byte3 AS _UNSIGNED _BYTE
byte4 AS _UNSIGNED _BYTE
byte5 AS _UNSIGNED _BYTE
byte6 AS _UNSIGNED _BYTE
byte7 AS _UNSIGNED _BYTE
byte8 AS _UNSIGNED _BYTE
byte9 AS _UNSIGNED _BYTE
byte10 AS _UNSIGNED _BYTE
byte11 AS _UNSIGNED _BYTE
byte12 AS _UNSIGNED _BYTE
byte13 AS _UNSIGNED _BYTE
byte14 AS _UNSIGNED _BYTE
byte15 AS _UNSIGNED _BYTE
byte16 AS _UNSIGNED _BYTE
byte17 AS _UNSIGNED _BYTE
byte18 AS _UNSIGNED _BYTE
byte19 AS _UNSIGNED _BYTE
byte20 AS _UNSIGNED _BYTE
END TYPE
DIM m AS _MEM 'A memblock to store some information
m = _MEMNEW(20) 'The proper size to fill the data type that we're interested in passing back to our program.
_MEMPUT m, m.OFFSET, "Hello World" '12 bytes
_MEMPUT m, m.OFFSET + 12, -2 AS LONG '4 more
_MEMPUT m, m.OFFSET + 16, 3 AS LONG '4 more to make all 20
SUB_EXAMPLE m.OFFSET 'Call the sub with the offset to these 20 bytes of memory
SLEEP
SUB_EXAMPLE2 m.OFFSET 'Notice, we passed the same block of memory, but are handling it differently here,
' according to the paramters set in the second sub
_MEMFREE m
END
SUB Example (t AS DataType) 'And here, we want to set up the actual sub to work with our example datatype.
PRINT t.x 'print the values of that memblock
PRINT t.y
PRINT t.z
END SUB
SUB Example2 (x AS DataType2)
COLOR 12
PRINT x.byte1
PRINT x.byte2
PRINT x.byte3
PRINT x.byte4
PRINT x.byte5
PRINT x.byte6
PRINT x.byte7
PRINT x.byte8
PRINT x.byte9
PRINT x.byte10
PRINT x.byte11
PRINT x.byte12
PRINT x.byte13
PRINT x.byte14
PRINT x.byte15
PRINT x.byte16
PRINT x.byte17
PRINT x.byte18
PRINT x.byte19
PRINT x.byte20
END SUB
|