13

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?

0

3 Answers 3

14

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

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

Sign up to request clarification or add additional context in comments.

1 Comment

Note that he did not really mean having to use assembler, but rather that it looks like assembler with all the masking/shifting required when you have to access such sub-fields manually.
9

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.

2 Comments

Just an addendum: I tried doing this with a struct (as opposed to just the one 'chunk' variable) with a uint16 and uint32, and unfortunately go gives a Sizeof() = 8, not 6 for the struct. Other than that, a big (belated) thank you for your answer, it was very helpful
Yeah, with a struct the members are likely to be word aligned. If you're already using "unsafe", you could use a [3]uint16 and get the uint32 part with "(*uint32)(unsafe.Pointer(&val[1]))", which avoids the cost of packing/unpacking, but it's a bit ugly.
0

I've created a Go tool that generates code to emulate bit fields. Basically you annotate a Go struct with struct tags indicating the width in bits of each field.

The tool then uses that as input to generate a Go type with getters and setters allowing to easily manipulate the bits.

github.com/arl/bitfield

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.