结构并集的去引用结构

De-referencing structure of union of structures

本文关键字:结构 引用      更新时间:2023-10-16
typedef struct
{
    int data1;
    float data2;
} packetType1;
typedef struct
{
     bool data1;
} packetType2;
typedef union
{
     packetType1 p1;
     packetType2 p2;
} packet;
struct
{
    int type;
    packet myPacket;
} message;

现在,我生成一条消息,并将指向此消息的指针传递给函数。在这个函数中,我需要取消引用消息并从中取出必要的数据。

此数据将取决于数据包是用数据包类型1 类型的数据填充的还是数据包类型2 类型的数据。内部消息,整数变量类型只能包含值 1 或 2,告诉消息内部的数据包是 packetType1 或 packetType2 类型。

我想知道这样做是否安全 -

packetType1 s1;
s1.data1 = 10;
s1.data2 = 22.22;

packetType2 s2;
s2.data1 = true; 
packet pack1; 
pack1.p1 = s1;
packet pack2;
pack2.p2 = s2;
message m1;
m1.type = 1;
m1.myPacket = pack1;
message m2;
m2.type = 2;
m2.myPacket = pack2;
eatPacket( &m1 );
eatPacket( &m2 );

void eatPacket( void *p )
{
    if( *(int*)p == 1)
    {
       message msg = *(message*)p
       cout << msg.myPacket.data1;
       cout << msg.myPacket.data2;
    }
    else if( *(int*)p == 2)
    {
       message msg = *(message*)p
       cout << msg.myPacket.data1;           
    }
}

编辑:(对于所有问我为什么使用void*的人(

这些消息使用 posix 消息队列从一个进程发送到另一个进程,然后在那里解码。问题是,即使这种消息结构也可能不同。我唯一可以肯定的是,变量 int 类型将始终在那里指导我。消息的其他部分可能会更改。所以我必须通过让它接受 void * 来使这个函数通用,然后使用变量类型提供的值在内部进行解码。

想想现在有人发出这样的消息——

struct
{
    int type;
    float data;
    bool moreData;
    int evenMoreData;
} newMessage;

对于此新消息,已决定变量类型的值始终为 3。

所以在我的 eat 函数中,我将添加另一个这样的子句

if( *(int*)p == 3)
{
       newMessage msg = *(newMessage*)p
       cout << msg.data;
       cout << msg.moreData;
       cout << msg.evenMoreData;
}

这样做是否仍然安全?我希望这现在有意义?

它看起来不错,但我会像这样重写eatPacket()

void eatPacket(const message& msg)
{
    if(msg.type == 1)
    {
       cout << msg.myPacket.data1;
       cout << msg.myPacket.data2;
    }
    else if(msg.type == 2)
    {
       cout << msg.myPacket.data1;           
    }
}

真的不需要我能看到的void*体操。 如果你真的需要msg成为指针,你可以用一种直接的方式修改上面的内容(->用于.等(。

我该怎么办?

void eatPacket( message* msg )
{
    if(NULL == msg) return;
    if( message->type == 1 )
    {
       cout << msg->myPacket.data1;
       cout << msg->myPacket.data2;
    }
    else if(message->type == 2 )
    {
       cout << msg->myPacket.data1;           
    }
}

按照自己的方式做安全吗?我真的不知道。什么是消息?

我不会做这些。我认为创建一个抽象的 BaseMessage 类,然后为 int 有效负载派生一个类,为布尔有效负载派生一个类会更干净。然后你可以有一个虚拟的 GetData(( 方法。当您将指针传递给基类时,将调用正确的虚函数来返回数据。联合几乎总是OO技术可以帮助解决的代码气味。我实际实现这一点的很多方式取决于消息的多样性以及它们最终的使用方式,但希望您能理解这个想法。