将结构转换为另一个结构以获取特定数据

时间:2013-06-17 14:57:38

标签: c casting struct

我有这个结构代表一般信息

typedef struct {
    uint16_t length;    
    uint8_t type1;      
    uint8_t type2;      
    uint8_t *data;      
} generic_msg_t;

在读取type1和type 2之后,我可以知道它对应哪个特定的消息,例如:

 typedef struct {
     uint16_t length;   
     uint8_t type1;     
     uint8_t type2;     
     uint16_t a;
     uint8_t b;
     uint8_t c;
     double d;
     double e;
     double f;
     double g;
     double h;
     uint8_t i;
 } specific_msg_t;

假设msg包含已验证的数据,我想了解为什么如果我这样做,我无法访问d,e,f,g,h数据(但是a,b,c)

specific_msg_t * specific_msg = (specific_msg_t *) msg;
uint16_t a = specific_msg->a; //OK
double d = specific_msg->d; //NOK`

我必须这样做:

unsigned char * buffer = (unsigned char *) msg;
double d = buffer[15] + (buffer[14] << 8) + (buffer[13] << 16) + (buffer[12] << 24) + (buffer[11] << 32) + (buffer[10] << 40) + (buffer[9] << 48) + (buffer[8] << 56);`

2 个答案:

答案 0 :(得分:0)

只要发送方和接收方使用相同的标头(uint16_t对于它们两者都相同)并且它们都使用相同的体系结构(例如x86或其他),就不应该有太多问题。 我还会定义一个你需要的所有特定消息类型的联合,以避免那些讨厌的计算和大多数演员。 类似的东西:

typedef struct {
    uint16_t length;    
    uint8_t type1;      
    uint8_t type2;   

    // whatever you need here...
    double a;
    float b;
    // etc.
} specific_msg_t1;

 typedef struct {
     uint16_t length;   
     uint8_t type1;     
     uint8_t type2;     
     uint16_t a;
     uint8_t b;
     uint8_t c;
     double d;
     double e;
     double f;
     double g;
     double h;
     uint8_t i;
 } specific_msg_t2;

 typedef struct
 {
    uint16_t length;    
    uint8_t type1;     
    uint8_t type2;     
 } selector_msg_t;

 typedef union
 {
    selector_msg_t  selector;
    specific_msg_t1 msgtype1;
    specific_msg_t2 msgtype2;
 } message_type_t;

使用此设置,您可以发送“message_type_t”类型的消息。使用成员“selector”决定您收到的特定类型的消息,然后使用适当的特定类型来读取不同的数据成员。 如果特定类型之间的大小差异相当大,那么这是一个坏主意,但如果您不受带宽的限制,那么它至少是可读的而不是容易出错的。

答案 1 :(得分:0)

specific_msg_t可能具有与generic_msg_t不同的对齐要求,因此在某些体系结构上,该代码可能会导致崩溃 - 编译器没有特别要求将generic_msg_t对象与适合访问的边界对齐双

确切地知道你会得到什么错误会有所帮助。