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;

在没有语言帮助的情况下执行此操作的另一种方法相当丑陋,并且几乎演变为汇编程序。例如,一种解决方案是为您要访问的每个字段设置位移宏:

#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 中没有 struct 位域的计划。”

您可以编写一个 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 中,您正在查看一个带有 ~6 条 getter 指令的函数调用,并且随着时间的推移,这些调用可能会被内联。

于 2011-05-03T04:52:20.960 回答