2010-08-26 109 views
3

此代码适用于Microchip的PIC32MX微处理器。他们的编译器基本上是GCC 3.4。冗余__packed__属性

我倾向于使用GCC的__packed__ attribute将位域打包到一个联合体中,稍后将它们检索为unsigned char(即,类型双引号)以通过SPI或I2C发送。这一行为全部由我的实现定义,并且完美地工作。我更喜欢这个到一百行左右的掩码和移位:)

我的问题是:在下面的代码中是否有__packed__属性是多余的?乍一看,我认为那些顶层工会成员可以放弃,但我不太确定。或者我可以忽略那些嵌套的结构?所有的

// Remember that bitfields cannot straddle word boundaries! 
typedef struct 
{ 
    /// Some flag #1 
    unsigned FlagOne   : 1 __attribute__((packed)); 
    /// Some flag #2 
    unsigned FlagTwo   : 1 __attribute__((packed)); 
    /// A chunk of data 
    unsigned SomeData   : 5 __attribute__((packed)); 

    // and so on, maybe up to 32 bits long depending on the destination 

} BlobForSomeChip; 

/// This kind of type-punning is implementation defined. Read Appendix A (A7, A12) of 
/// the MPLAB C Compiler for PIC32 MCUs manual. 
typedef union 
{ 
    /// Access the members of this union to set flags, etc 
    BlobForSomeChip blobdata __attribute__((packed)); 

    /// As a byte for sending via SPI, I2C etc 
    unsigned char bytes[4] __attribute__((packed)); 

} BlobData; 

回答

2

首先,我建议您用-Wall编译。

现在:

  1. BlobForSomeChip结构有7位声明。通常,由于对齐,它将是4个字节长,但是打包的属性只有1个字节长。
  2. A unsigned char[4]不能打包。无论如何,它总是4个字节。

简而言之:

  1. struct BlobForSomeChip = 1字节
  2. unsigned char[4] = 4字节
  3. BlobData = 4字节(其最大的成员的大小)。

结论是,不需要BlobData上的打包属性。如果使用GCC,它将忽略它们 - 请参阅使用-Wall的输出。

+0

对于上面的第1点 - “//等等”注释意味着暗示它可以是长达32位的任何东西。通常情况下,我会填入任何短于8位的未命名位域。因此,请考虑“BlobForSomeChip”正好是32位的情况(但我认为您的解释也适用)。 – detly 2010-08-26 02:09:12

+0

@detly:正确,字节大小始终为ceil(总位数/ 8)。打包的属性只能删除填充/对齐。 N个显式/声明位总是N位。 – jweyrich 2010-08-26 02:24:27

+0

'-Wall'在GCC 3.4上似乎没有捕捉到这一点(至少在MC的编译器中)。我将检查Debian打包版本。但除此之外,很好的解释,谢谢:) – detly 2010-08-26 02:26:22