访问工会内的工会成员时出错

问题描述 投票:0回答:1

我在加入这个工会时遇到问题:

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) 相同

我看不出有什么问题,有人可以帮我吗?

编辑: 解决方案是为联合添加“attribute((packed))”

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 
c++ unions arduino-c++
1个回答
0
投票

你有一个小端机器。因此,

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
),或者改变结构中字段的顺序。你还需要告诉你的编译器创建一个“打包”结构(即省略填充)。

© www.soinside.com 2019 - 2024. All rights reserved.