Why element size is not 2?
#1
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?


Reply
#2
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.


Reply
#3
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.
Reply
#4
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 + ...
Reply
#5
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 + ...
Reply
#6
@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.


Reply
#7
(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 + ...
Reply
#8
(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.
Reply
#9
@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 + ...
Reply
#10
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
Reply




Users browsing this thread: 6 Guest(s)