Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go: Bitfields and bit packing

Tags:

go

bit-fields

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?

like image 519
Rooke Avatar asked Apr 26 '11 16:04

Rooke


2 Answers

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.

like image 136
Kyle C Avatar answered Oct 25 '22 21:10

Kyle C


"There are no current plans for struct bitfields in Go."

You could write a Go package to do this; no assembler is required.

like image 45
peterSO Avatar answered Oct 25 '22 23:10

peterSO