Strucutre : n

Just starting out? Need help? Post your questions and find answers here.
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Strucutre : n

Post 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
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
kenmo
Addict
Addict
Posts: 2047
Joined: Tue Dec 23, 2003 3:54 am

Re: Strucutre : n

Post 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.
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Strucutre : n

Post by nco2k »

cool thanks. :)

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
idle
Always Here
Always Here
Posts: 5932
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Strucutre : n

Post 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)
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5932
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Strucutre : n

Post 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) 

Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Strucutre : n

Post 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 ^^
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Strucutre : n

Post 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
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
mhs
Enthusiast
Enthusiast
Posts: 101
Joined: Thu Jul 02, 2015 4:53 pm
Location: Germany
Contact:

Re: Strucutre : n

Post 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.
User avatar
idle
Always Here
Always Here
Posts: 5932
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Strucutre : n

Post 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)
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Strucutre : n

Post by nco2k »

a c long is always 32bit, unless visual studio just lied to me. :)

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
idle
Always Here
Always Here
Posts: 5932
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Strucutre : n

Post by idle »

Thanks, I didn't know that, on linux it's the native size and probably the same for osx
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Shield
Addict
Addict
Posts: 1021
Joined: Fri Jan 21, 2011 8:25 am
Location: 'stralia!
Contact:

Re: Strucutre : n

Post 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.
Image
Blog: Why Does It Suck? (http://whydoesitsuck.com/)
"You can disagree with me as much as you want, but during this talk, by definition, anybody who disagrees is stupid and ugly."
- Linus Torvalds
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Strucutre : n

Post 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
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Strucutre : n

Post 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 
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
idle
Always Here
Always Here
Posts: 5932
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Strucutre : n

Post 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"  

Windows 11, Manjaro, Raspberry Pi OS
Image
Post Reply