我有一个结构体,如下所示:
typedef struct st_MASK_SETTINGS
{
uint32_t foo : 1;
uint32_t bar : 7;
} MASK_SETTINGS
现在通过cgo我想要访问foo
- 但是找不到任何关于如何这样做的文档。
简单地写下v := ms.foo
会提示没有该字段或方法
。
好吧,你可能不会喜欢这个答案,但是:
首先,所有现有的C和C++标准中,位域的布局都是实现定义的。这意味着标准都没有规定位域定义中的位应该如何打包(即放在哪里)——完全取决于编译器。尽管你可以通过一些编译器样例找到它们的布局方式,但你将深入未定义行为的领域。
我们正在bug #83784下解决gcc中的这个问题(“我们”指的是Andrew Pinski),我希望在gcc 10或11中我们能够得到最优解决方案。明确一点,现在已经有一个解决方案——使用联合并定义打包和解包函数来读取每个位域,并手动将数据放置在内存中的正确位置。问题在于,当您正确猜测了gcc使用的位布局时,该函数应该变成无操作并“编译消失”。但目前还没有发生这种情况。union a {
struct {
int field1:12;
int field2:20;
};
int packed;
};
static union a a_pack(union a a)
{
union a ret = {0};
ret.packed = (a.field1 & ((1 << 12) - 1) << 20;
ret.packed |= a.field2 & ((1 << 20) - 1)
return ret;
}
static union a a_unpack(union a a)
{
union a ret = {0};
ret.field1 = a.packed >> 20;
ret.field2 = a.packed & ((1 << 20) - 1);
return ret;
}
ms & 0x80 != 0
和ms & 0x7f
有什么问题? - Volkerms
是MASK_SETTINGS
的一个实例。如果我直接访问它,它的类型是_Ctype_struct_MASK_SETTINGS
,因此无法进行移位等操作。当然,我可以编写一个 C 函数,将foo
和bar
组合成uint32_t
并在 Go 中使用该值。我想知道是否有任何机会在不编写 C 代码的情况下使用位域。如果这不是您的意思,请说明一下。 - abergmeier