11

C 言語のビットフィールドは、構造体内で任意の幅のフィールドを定義するための非常に便利な方法を提供します (移植性の問題については、しばらく気にしないでください)。たとえば、次の例は、いくつかのフィールドと「フラグ」を持つ単純な構造です。

#pragma pack(push,1)
struct my_chunk{

    unsigned short fieldA: 16;
    unsigned short fieldB: 15;
    unsigned short fieldC:  1;
};
#pragma pop()

#pragma ステートメントを追加すると、この構造体が 32 ビット ワードにパックされます (my_chunkたとえば、スペースの節約とともに、ポインターのポインター操作が整列されるようになります)。

各フィールドへのアクセスは、構文的に非常に優れています。

struct my_chunk aChunk;
aChunk.fieldA = 3;
aChunk.fieldB = 2;
aChunk.fieldC = 1;

言語の助けを借りずにこれを行う別の方法は、かなり醜く、ほとんどアセンブラーに委ねられます。たとえば、1 つの解決策は、アクセスするフィールドごとにビットシフト マクロを用意することです。

#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);

.. または大まかにそのようなもの (より形式的には、これを見てください)

質問は、go でビットフィールドを「実行」したい場合、そのためのベストプラクティスは何ですか?

4

2 に答える 2

13

「Go の構造体ビットフィールドに関する現在の計画はありません。」

これを行うために Go パッケージを作成できます。アセンブラは必要ありません。

于 2011-04-26T17:54:09.797 に答える
8

目標が非常に小さな構造体を持つことだけである場合は、おそらく次のようにします。

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())
}

現在の 6g/8g では、getter に対して最大 6 つの命令を含む関数呼び出しが表示されており、時間の経過とともに、そのような呼び出しはおそらくインライン化されます。

于 2011-05-03T04:52:20.960 に答える