The C language's bitfields provide a fairly convenient method of defining arbitrary-width fields within a structure (nevermind the problems with portability for a minute.) For example, here's a simple structure with a couple fields and a 'flag':
#pragma pack(push,1)
struct my_chunk{
unsigned short fieldA: 16;
unsigned short fieldB: 15;
unsigned short fieldC: 1;
};
#pragma pop()
Adding the #pragma statements packs this structure into a 32-bit word (ensuring that pointer manipulations of my_chunk
pointers are aligned, for example, along with space savings).
Accessing each field is syntactically very nice:
struct my_chunk aChunk;
aChunk.fieldA = 3;
aChunk.fieldB = 2;
aChunk.fieldC = 1;
The alternate way of doing this without the language's help is rather ugly and pretty much devolves into assembler. e.g. one solution is to have bitshift macros for each field you want to access:
#define FIELD_A 0xFF00
#define FIELD_B 0x00FE
#define FIELD_C 0x0001
#define get_field(p, f) ((*p)&f)
#define set_field(p, f, v) (*p) = (v<<f) + (*p)&(~f)
...
set_field(&my_chunk, FIELD_A, 12345);
.. or something roughly like that (for more formality, take a look at this)
So the question is, if I want to "do" bitfields in go, what is the best practice for doing so?
If the goal is just to have a very small struct, you'd probably just do:
package main
import "fmt"
type my_chunk uint32
func (c my_chunk) A() uint16 {
return uint16((c & 0xffff0000) >> 16)
}
func (c *my_chunk) SetA(a uint16) {
v := uint32(*c)
*c = my_chunk((v & 0xffff) | (uint32(a) << 16))
}
func main() {
x := my_chunk(123)
x.SetA(12)
fmt.Println(x.A())
}
With the current 6g/8g, you're looking at a function call with ~6 instructions for the getter, and with time such calls will probably be inlined.
"There are no current plans for struct bitfields in Go."
You could write a Go package to do this; no assembler is required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With