Page 1 of 1
Strucutre : n
Posted: Sun Apr 17, 2016 5:35 am
by nco2k
a somewhat stupid question, but what does : n mean? how do you translate it to pb? i never seen it before.
Code: Select all
typedef struct abc {
ULONG def : 1;
ULONG ghi : 21;
}
c ya,
nco2k
Re: Strucutre : n
Posted: Sun Apr 17, 2016 5:48 am
by kenmo
It's a "bit field", it means those struct members in your example take up 1 bit and 21 bits respectively, probably in one shared integer.
If you check sizeof(struct abc) I think it would give 4 bytes (it rounded up to 32 bits).
https://en.wikipedia.org/wiki/Bit_field
I don't think there's a direct way to do this in PB, you will have to do some bitshift manipulation to set/get those values.
Re: Strucutre : n
Posted: Sun Apr 17, 2016 6:14 am
by nco2k
cool thanks.
c ya,
nco2k
Re: Strucutre : n
Posted: Mon Apr 18, 2016 4:16 am
by idle
Quick idea to work with bit fields
Code: Select all
Define.i BF_Index,BF_Offset,BF_Mask
Macro NewBitField(BitField,NumFields)
BF_Index = 0
BF_Offset = 0
Global Dim BF_#BitField.i(1,NumFields)
EndMacro
Macro BF_32(BitField,NumBits)
BF_Mask = $FFFFFFFF
BF_Mask >> (32-NumBits)
BF_#BitField(0,BF_Index) = (BF_Mask << BF_Offset)
BF_#BitField(1,BF_Index) = BF_Offset
BF_Offset+NumBits
BF_Index+1
EndMacro
Macro BF_Get(Var,BitField,Index)
((var & BF_#BitField(0,index)) >> BF_#BitField(1,index))
EndMacro
Macro BF_Set(Var,BitField,index,val)
var | (val << BF_#BitField(1,index))
EndMacro
Enumeration ;indexes to bitfield entries
#Foo1
#Foo21
#Foo9
EndEnumeration
NewBitField(foo,3) ;Define a Bit Field
BF_32(foo,1) ;Define the field width
BF_32(foo,21)
BF_32(foo,9)
Global b.l
BF_Set(b,foo,#Foo1,1) ;set the var at the Bit Field define with the value
BF_Set(b,foo,#Foo21,2097151)
BF_Set(b,foo,#Foo9,511)
Debug BF_Get(b,foo,#Foo1) ;get the value by the Bit Field define
Debug BF_Get(b,foo,#Foo21)
Debug BF_Get(b,foo,#Foo9)
Re: Strucutre : n
Posted: Mon Apr 18, 2016 8:08 am
by idle
or like this maybe, so you can work with it internally or externally through the macros
for internal use
GetBitfield(Bitfield,Index)
SetBitField(BitField,index,val)
for external use, set a pointer to an external variable and use the addressed mode
SetBitFieldPointer(BitField,Address) ;reassign a bit fields pointer to an external variable
GetBitFieldAddressed(BitField,Index)
SetBitFieldAddressed(BitField,Index,value)
Code: Select all
Structure BitField
*bits.Integer
Size.l
Addressed.l
BF_Index.l
BF_Offset.l
BF_Mask.i
Array BF.i(1,0)
EndStructure
Procedure NewBitField(NumFields,Address=0,size=4)
Protected *this.BitField
*this = AllocateStructure(BitField)
If *this
*this\size = size
If Address
*this\bits = Address
*this\Addressed = 1
EndIf
ReDim *this\bf(1,NumFields)
ProcedureReturn *this
EndIf
EndProcedure
Procedure FreeBitField(*BitField)
FreeStructure(*BitField)
EndProcedure
Procedure AddBitField(*BitField.BitField,NumBits)
Select *BitField\size
Case 4
*BitField\BF_Mask = $FFFFFFFF
*BitField\BF_Mask >> (32-NumBits)
Case 8
*BitField\BF_Mask = $FFFFFFFFFFFFFFFF
*BitField\BF_Mask >> (64-NumBits)
EndSelect
*BitField\bf(0,*BitField\BF_Index) = (*BitField\BF_Mask << *BitField\BF_Offset)
*BitField\bF(1,*BitField\BF_Index) = *BitField\BF_Offset
*BitField\BF_Offset + NumBits
*BitField\BF_Index+1
EndProcedure
Macro GetBitfield(Bitfield,Index)
((BitField\bits & BitField\bf(0,index)) >> BitField\bf(1,index))
EndMacro
Macro GetBitFieldAddressed(BitField,Index)
((BitField\bits\i & BitField\bf(0,index)) >> BitField\bf(1,index))
EndMacro
Macro SetBitFieldAddressed(BitField,index,val)
BitField\bits\i | (val << BitField\bf(1,index))
EndMacro
Macro SetBitField(BitField,index,val)
BitField\bits | (val << BitField\bf(1,index))
EndMacro
Macro SetBitFieldPointer(BitField,Address)
BitField\bits = Address
EndMacro
;example
Enumeration ;set up indexes to bitfield entries identifying their size
#Foo1
#Foo21
#Foo9
EndEnumeration
Global *foo.BitField ,*bar.BitField
*foo = NewBitField(3) ;Define a Bitfield
AddBitField(*foo,1) ;set up field widths for foo
AddBitField(*foo,21)
AddBitField(*foo,9)
SetBitField(*foo,#Foo1,1) ;set the var by it's bit field def at index with the value
SetBitField(*foo,#Foo21,2097151)
SetBitField(*foo,#Foo9,511)
Debug GetBitfield(*foo,#Foo1) ;get the value by field defention at index
Debug GetBitfield(*foo,#Foo21)
Debug GetBitfield(*foo,#Foo9)
*bar = NewBitField(3,@*Foo\bits) ;define a new bit field bit but set to an external var
AddBitField(*bar,1) ;set up the field widths
AddBitField(*bar,21)
AddBitField(*bar,9)
Debug GetBitFieldAddressed(*bar,#foo1)
Debug GetBitFieldAddressed(*bar,#foo21)
Debug GetBitFieldAddressed(*bar,#foo9)
Global bits.l
SetBitFieldPointer(*bar,@bits) ;reasign bars pointer to bits
SetBitFieldAddressed(*bar,#foo1,1) ;sets bits values via bar
SetBitFieldAddressed(*bar,#foo21,1024)
SetBitFieldAddressed(*bar,#foo9,256)
Debug GetBitFieldAddressed(*bar,#foo1)
Debug GetBitFieldAddressed(*bar,#foo21)
Debug GetBitFieldAddressed(*bar,#foo9)
FreeBitField(*foo)
FreeBitField(*bar)
Re: Strucutre : n
Posted: Mon Apr 18, 2016 12:44 pm
by Lunasole
ULONG is unsigned long, Pb doesn't have unsigned long, but for bitmask it doesn't matter. The translation should be
Code: Select all
Structure abc
def.l
ghi.l
EndStructure
Also should notice that in purebasic long size is always 4 bytes (both on windows and linux), in C/C++ compilers it can vary from 4 to 8 bytes (comparing windows and linux), such freedom of types implementation/defines/redefines sometimes makes porting of C/C++ code to other compiler or platform very funny ^^
Re: Strucutre : n
Posted: Mon Apr 18, 2016 1:29 pm
by nco2k
wrong, the bitfield actually shares the long.
Code: Select all
//in C (32 bits, 4 byte)
struct Test {
long var1 : 8;
long var2 : 1;
long var3 : 23;
};
//in PB (32 bits, 4 byte)
Structure Test
bitfield.l
EndStructure
c ya,
nco2k
Re: Strucutre : n
Posted: Mon Apr 18, 2016 3:16 pm
by mhs
nco2k wrote:wrong, the bitfield actually shares the long.
Yes, that's right. It's the main advantage of bit fields in C.
Re: Strucutre : n
Posted: Mon Apr 18, 2016 9:22 pm
by idle
A c long is equivalent to a pb integer so for 32 bit it's 4 bytes and x64 8 bytes
when you encounter a bit field ":" in a struct the type specifies the size of a shared variable
followed by the number of bits used so the c preprocessor can do the fix ups to set and get the field vars
To access the fields you need a set of masks and offsets
Code: Select all
#mask_var1 = %00000000000000000000000011111111 ;; 8
#mask_var2 =%00000000000000000000000100000000 ;: 1
#mask_var3 =%11111111111111111111111000000000 ;: 23
#ofs_var1=0
#ofs_var2 = 8
#ofs_var3 = 9
;to get a field value
x = ((var & mask) >> ofs)
;to set a field
var | (val << ofs)
or you can try one of the codes I posted which does the same, the second version you can reuse as a template
but you may need to reset the field pointer before accessing fields with
SetBitFieldPointer(BitField,Address)
then use the get macro to assign compare of do what ever you need to do
GetBitFieldAddressed(*bitfield_foo,#foo1)
Re: Strucutre : n
Posted: Tue Apr 19, 2016 7:00 am
by nco2k
a c long is always 32bit, unless visual studio just lied to me.
c ya,
nco2k
Re: Strucutre : n
Posted: Tue Apr 19, 2016 7:15 am
by idle
Thanks, I didn't know that, on linux it's the native size and probably the same for osx
Re: Strucutre : n
Posted: Wed Apr 20, 2016 2:05 am
by Shield
nco2k wrote:a c long is always 32bit, unless visual studio just lied to me.
No, the long type is
at least 32 bit. What it actually is is depending on
the compiler and platform, but it definitely isn't always 32 bit.
If you want a type with a certain size in C, you have to include stdint.h and use
fixed with types such as int32_t.
Re: Strucutre : n
Posted: Wed Apr 20, 2016 7:28 am
by nco2k
yes and here its 32bit. Lunasole and idle already pointed out, that it may be different on other platforms. btw the at least statement applies for almost every type (char, short etc.), thats why fixed width integers were introduced in the first place. but you are right, i shouldnt have written always, as it could cause confusion.
c ya,
nco2k
Re: Strucutre : n
Posted: Wed Apr 20, 2016 6:19 pm
by Lunasole
nco2k wrote:wrong, the bitfield actually shares the long.
Code: Select all
//in PB (32 bits, 4 byte)
Structure Test
bitfield.l
EndStructure
Yes I missed, never encountered with those bitfields before and didn't even know about them (just assumed, as it often with me in such cases ^^) until you told I'm wrong.
What I read right now about them looks interesting way to set bits.
But can't say it is better than "classical" path like following example, C declaration when every bit has its own variable seems excessive enough and might be confusing when reading code using it.
Code: Select all
; check if specified value has specified bit set up
; "Value" is bitmask, "Bit" is int representing bit # (starting from 1, up to 32 or more)
; RETURN: 1 or 0
Macro BitGet (Value, Bit)
Bool(Value & (1 << (Bit - 1))) ; also: ((Value & (1 << (Bit - 1))) >> (Bit - 1)), ~~(Value & (1 << (Bit - 1))) ; (both won't work nice)
EndMacro
; set up specified bit
; "Value" is bitmask, "Bit" is int representing bit # (starting from 1, up to 32 or more)
; RETURN: modified bitmask (or result stored inside Value, if no assigment)
Macro BitSet (Value, Bit)
Value | (1 << (Bit - 1)) ; this macro IS NOT SAFE in expressions where it surrounded by "~,<<,>>,%,!" operators. Add brackets to this string for this (that will also disallow use w/o assigment).
EndMacro
; removes specified bit
; "Value" is bitmask, "Bit" is int representing bit # (starting from 1, up to 32 or more)
; RETURN: modified bitmask (or result stored inside Value, if no assigment)
Macro BitOff (Value, Bit)
Value ! (1 << (Bit - 1)) ; this macro IS NOT SAFE in expressions where it surrounded by "~,<<,>>,%" operators. Add brackets to this string for this (that will also disallow use w/o assigment).
EndMacro
;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;
Structure Test
bitfield.l
EndStructure
Define T.Test
BitSet(T\bitfield, 2) ; now bit #2 is set (or bit 1, if start counting from 0)
T\bitfield = BitSet(T\bitfield, 22) ; the same for bit 22 (21)
Debug T\bitfield
T\bitfield = BitOff(T\bitfield, 2)
BitOff(T\bitfield, 22) ; same for bit 22 (21)
Debug T\bitfield ; 0
Re: Strucutre : n
Posted: Wed Apr 20, 2016 8:56 pm
by idle
Lunasole wrote:
But can't say it is better than "classical" path like following example, C declaration when every bit has its own variable seems excessive enough and might be confusing when reading code using it.
When it comes to single bits the overhead of setting up a mask and offsets might seem excessive but then that's what the compiler should do.
Though when you encounter a bit field in a structure, they're rarely used for single bits alone, which is why you need to mask them.
In the case of single bits you can also use assembly instructions BTS BTR BTC but then you can't really use them via a macro in expressions
but it's easy enough to inline them.
Also the index is from 0
Code: Select all
Macro BitSet(var, bit)
var | (1 << bit)
EndMacro
Macro BitClear(var,bit)
var & ~(1 << bit)
EndMacro
Macro BitCompliment(var, bit)
var ! (1 << bit)
EndMacro
Macro BitGet(var, bit)
(var >> bit) & 1
EndMacro
BitField.l
BitSet(BitField,1)
BitSet(BitField,30)
Debug RSet(Bin(BitField,#PB_Long),32,"0") + " set 1 and 30"
BitClear(BitField,1)
Debug RSet(Bin(BitField,#PB_Long),32,"0") + " cleared 1"
BiTCompliment(BitField,1)
BitCompliment(BitField,30)
Debug RSet(Bin(BitField,#PB_Long),32,"0") + " toggled 1 and 30, 1 on 30 off"
Debug Str(Bitget(BitField,1)) + " on" ;> 0 true
!BTS [v_BitField],30 ;Bit Test Set
Debug Str(Bitget(BitField,30)) + " on";> 0 true
!BTR [v_BitField],1 ;Bit Test Reset
Debug Str(Bitget(BitField,1)) + " off"; off
!BTC [v_BitField],1 ;Bit Test Compliment
Debug Str(Bitget(BitField,1)) + " on"