数组+联合+包含位字段C ++的结构

时间:2012-10-17 17:44:34

标签: c++ arduino avr-gcc

我只是玩弄了一些字段,遇到了一些我无法弄清楚如何到处走走的东西。

(关于平台的注意事项:int的大小= 2bytes,long = 4bytes,long long = 8bytes - 认为值得一提,因为我知道它可以变化。'byte'类型被定义为'unsigned char' )

我希望能够创建一个包含两个36位变量的数组,并将它们放入一个9字节数组的联合中。这就是我想出的:

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; 

1 个答案:

答案 0 :(得分:6)

如果希望每个位域都精确到36位宽,则无法使用数组直接执行此操作。

指针必须与字节边界对齐,这就像指针一样。由于数组在大多数情况下都像指针一样运行(有例外),这对于包含多个位的位域是不可能的,这些位不能被8整除。(如果位域被打包,你会期望&(((Colour *) 0)->integers[1])返回什么?什么价值才有意义?)

在你的第二个例子中,位域可以紧密包装,因为引擎盖下没有指针数学。对于可由指针寻址的东西,它们必须落在字节边界上,因为字节是用于“测量”指针的单位。

您将注意到,如果您尝试在第二个示例中使用(((Colour *) 0)->integers.data0)data1的地址,编译器将发出错误,正是出于这个原因。