引用结构联合的结构

时间:2012-02-09 18:26:40

标签: c++ c structure dereference unions

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;

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

此数据取决于数据包是否填充了packetType1类型或packetType2类型的数据。在内部消息中,整数变量类型只能包含值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;
}

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

3 个答案:

答案 0 :(得分:3)

看起来不错,但我会像这样重写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作为指针,则可以直接修改上述内容(-> .等)。

答案 1 :(得分:1)

我该怎么办?

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;           
    }

}

按自己的方式行事是否安全?我真的不知道。什么是留言?

答案 2 :(得分:1)

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