首页 > 解决方案 > 位域实际上是如何工作的?在什么情况下会发生位填充?

问题描述

我最近被介绍到位域。我有一个以下工会。

 typedef struct
  {
            uint16_t        var1:16;         
            uint32_t       var2:28;         
            uint8_t        var3:8;       
            uint8_t        var4:8;     
            uint8_t        var5:8;   
            uint8_t        var6:8;  
            bool        var7:1;  
            bool         var8:1;          
            bool         var9:1;    
            bool         var10:1;  
            bool         var11:1;    
            uint8_t         var12:1;    
            uint8_t        var13:7;        
            uint8_t        var14:7;   
            uint32_t       var15:18;           
            uint16_t       var16:10;         
            uint8_t        var17:4;         
  } packet_bit_map;
typedef union
{

packet_bit_map packetsArrived ;
  uint8_t packetRaw[16];
} packetDecode;

这个想法是复制来自外部设备的数据流,它是 16 个字节的单个字节值,然后使用位域结构来访问特定信息。但是在调试后我无法做到这一点,我发现联合packetDecode的大小最终为 20 而不是 16 ,因为packetArrived持有 20bytes 。为什么会这样?以及如何避免这种填充?

编辑:我知道一种使用属性填充的解决方案,但遗憾的是我不能在我的项目中使用内联函数。

标签: cembeddeddeserializationunionbit-fields

解决方案


如果你想打包:

  1. 将字段分组为完全适合的类型。
  2. 不要bool用作位域的类型。
  3. 打包结构(它取决于实现)
 typedef struct __attribute__((packed))
  {
            uint16_t        var1:16;         
            uint64_t        var2:28;         
            uint64_t        var3:8;       
            uint64_t        var4:8;     
            uint64_t        var5:8;   
            uint64_t        var6:8;  
            uint64_t        var7:1;  
            uint64_t        var8:1;          
            uint64_t        var9:1;    
            uint64_t        var10:1;  
            uint16_t        var11:1;    
            uint16_t        var12:1;    
            uint16_t        var13:7;        
            uint16_t        var14:7;   
            uint32_t        var15:18;           
            uint32_t        var16:10;         
            uint32_t        var17:4;         
  } packet_bit_map;

https://godbolt.org/z/Pz3YzEE76


推荐阅读