我只是在玩位域,遇到了一些我不太清楚如何解决的问题。
(关于平台的注意事项:int 的大小 = 2 字节,long = 4 字节,long long = 8 字节 - 认为值得一提,因为我知道它可能会有所不同。此外,'byte' 类型被定义为 'unsigned char' )
我希望能够创建一个包含两个 36 位变量的数组,并将它们放入一个包含 9 个字节的数组的 union 中。这是我想出的:
typedef union {
byte bytes[9];
struct {
unsigned long long data:36;
} integers[2];
} Colour;
我的理论是,编译器会意识到应该有两个位域作为匿名结构的一部分,并将它们放在 9 字节的空间中。然而,事实证明它们在字节边界处对齐,因此并集占用 10 个字节而不是 9 个字节,这非常合理。
那么问题是,有没有一种方法可以像这样创建一个包含两个位字段的数组?我考虑过 'packed' 属性,但编译器只是忽略了它。
虽然这按预期工作(sizeof() 返回 9):
typedef union {
byte bytes[9];
struct {
unsigned long long data0:36;
unsigned long long data1:36;
} integers;
} Colour;
最好将其作为数组访问。
编辑: 感谢 cdhowie 解释了为什么这行不通。
幸运的是我想到了一个方法来实现我想要的:
typedef union {
byte bytes[9];
struct {
unsigned long long data0:36;
unsigned long long data1:36;
unsigned long long data(byte which){
return (which?data1:data0);
}
void data(byte which, unsigned long long _data){
if(which){
data1 = _data;
} else {
data0 = _data;
}
}
} integers;
} Colour;
最佳答案
如果您希望每个位域正好是 36 位宽,则不能直接使用数组来执行此操作。
指针必须与字节边界对齐,指针就是这样。由于在大多数情况下数组的功能类似于指针(有异常(exception)),这对于包含许多不能被 8 整除的位的位域来说是不可能的。(你会期望 &(((Colour *) 0)->integers[1])
如果位域被打包则返回?什么值才有意义?)
在您的第二个示例中,位域可以紧密打包,因为幕后没有进行指针数学运算。对于可通过指针寻址的事物,它们必须落在字节边界上,因为字节是用于“测量”指针的单位。
您会注意到,如果您尝试在第二个示例中获取 (((Colour *) 0)->integers.data0)
或 data1
的地址,正是由于这个原因,编译器将发出错误。
关于c++ - 数组 + union + 包含位字段 C++ 的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12940211/