访问联合内部的联合成员时出错



我在访问这个联合时遇到问题:

typedef union{ 
struct{    
uint8_t SA : 8; //! Source Address   
union { //! Protocol Data Unit
struct {      
uint8_t SPECIFIC : 8;     
uint8_t FORMAT : 8;
} ;
uint16_t PDU2 ;
};    
uint8_t DP : 1; //! Data Page    
uint8_t Reserved : 1;  //! Reserved = 0   
uint8_t PRIORITY : 3;   //! Priority   
uint8_t Reserved1 : 3;  //! Reserved = 0
};  
uint32_t word;  //single 32-bit word
}  J1939_ID 

在ESP32 中执行下一个

J1939_ID J1939_RxId;
J1939_RxId.word = 0x11223344;
Serial.println(J1939_RxId.word, HEX);
Serial.println(J1939_RxId.SA, HEX);
Serial.println(J1939_RxId.PDU2, HEX);
Serial.println(J1939_RxId.FORMAT, HEX);
Serial.println(J1939_RxId.SPECIFIC, HEX);

PDU2是0x1122,而不是我想要的0x2233,FORMAT(0x22(和SPECIFIC(0x33(相同

我看不出哪里出了问题,有人能帮帮我吗?

编辑:溶液加入">属性((压缩((";工会

typedef union{ 
struct{    
uint8_t SA : 8; //! Source Address   
union { //! Protocol Data Unit
struct {      
uint8_t SPECIFIC : 8;     
uint8_t FORMAT : 8;
} ;
uint16_t PDU2 ;
}__attribute__((packed));    
uint8_t DP : 1; //! Data Page    
uint8_t Reserved : 1;  //! Reserved = 0   
uint8_t PRIORITY : 3;   //! Priority   
uint8_t Reserved1 : 3;  //! Reserved = 0
};  
uint32_t word;  //single 32-bit word
} __attribute__((packed)) J1939_ID 

您有一个小型的endian机器。因此,RxId.word看起来像

+----+----+----+----+
| 44 | 33 | 22 | 11 |
+----+----+----+----+

您的编译器使用";正常填充约定";,因此,您的结构更接近以下内容(省略了一些不相关的细节(:

struct {
uint8_t SA;          // Aligned to an offset divisible by 1.
uint8_t __padding1;
uint16_t PDU2;       // Aligned to an offset divisible by 2.
uint8_t flags;       // Aligned to an offset divisible by 1.
uint8_t __padding2;  
}                       // Size must be divisible by 2 (largest of above).

把两者放在一起,我们得到

struct { 
uint8_t  SA;         // 0x44
uint8_t  __padding;  // 0x33
uint16_t PDU2;       // 0x1122
uint8_t  flags;      // 0x00 or uninitialized, not sure.
}

如果要继续使用并集,则需要将单词从本端序转换为大端序(例如使用htonl(,或者更改结构中字段的顺序。您还需要告诉编译器创建一个";包装的";struct(即省略填充(。

最新更新