C ++,使用可选值创建结构

时间:2020-10-12 10:32:42

标签: c++ struct

我需要创建一个带有可选值的结构:

typedef struct pkt_header{
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    unsigned short Protected_Payload_Length; // optional (present/not present)
    unsigned short Version;   
} PKT_HEADER;

当不存在该字段时,我如何有时使用pkt_header->Protected_Payload_Length,有时不使用struct中的该值? 我的第一个想法是声明unsigned char * Protected_Payload_Length并在我不使用该字段时传递NULL并使用unsigned char*存储我的unsigned short值。

typedef struct pkt_header{
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    unsigned char * Protected_Payload_Length; // optional
    unsigned short Version;   
} PKT_HEADER;

我这样准备包裹(并发送):

PKT_HEADER header;
header.Packet_Type                = 0x0001;
header.Unprotected_Payload_Length = 0x0b00;
header.Protected_Payload_Length   = NULL; 
header.Version                    = 0x0000;

我收到回复并执行此操作:

PKT_HEADER * header= (PKT_HEADER*)recvbuf;
printf("Packet_Type                : %04x\n", header->Packet_Type);
printf("Unprotected_Payload_Length : %04x\n", header->Unprotected_Payload_Length);
printf("Version                    : %04x\n", header->Version);

但是在这种情况下,如果我理解正确,unsigned char * Protected_Payload_Length包含一个指针,该指针的长度为4个字节,那么header->Protected_Payload_Length包含4 bytes,但是我需要0 byte,因为该值/ field在这种情况下不存在。

我是否必须以数据格式声明适当的结构,或者还有其他方法可以使用这些结构?

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

当心。结构可以填充,成员在内存中不一定相邻。此外,当某物不是PKT_HEADER对象时,不允许将某物重新解释为PKT_HEADER。而不是投射:

PKT_HEADER * header= (PKT_HEADER*)recvbuf; 

您可能应该使用memcpy。话虽如此,现在是您的实际问题...

如果您依赖于结构中具有特定顺序的成员,则继承不是一种选择。在内存中,基础对象首先出现,然后是派生成员,您无法将其混合。例如

 struct foo {
     int x;
 };
 struct bar : foo {
     int y;
     int z;
 };

然后bar对象将在内存中

 | x | optional padding | y | optional padding | z | optional padding |

没有简单的方法来获取| y | x | z |

如果要使用两种不同的类型,最简单的方法是定义两种不同的类型:

struct PKT_HEADER_A {
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    unsigned short Protected_Payload_Length; // present
    unsigned short Version;   
};


struct PKT_HEADER_B {
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    //unsigned short Protected_Payload_Length; // not present
    unsigned short Version;   
};

请注意,您使用typedef结构的方式是C-ism。在C ++中是不必要的(也不推荐)。

答案 1 :(得分:0)

您可能应该看一下在NanoPb或Protobuff上完成的包装,因为这听起来像您有包装问题。在发送数据之前,应该将数据拼凑在一起,然后Packet_Type将对要解码/编码的标头进行编码。

如果您无法正确打包/拆包,则可以同时创建两者

typedef struct {
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    unsigned short Protected_Payload_Length;
    unsigned short Version;   
} PKT_HEADER_FULL;

typedef struct {
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    unsigned short Version;   
} PKT_HEADER_SHORT;

然后创建您的数据包标头

typedef union u{
    PKT_HEADER_FULL full;
    PKT_HEADER_SHORT concat;
}PKT_HEADER;


// or as this

typedef struct{
    unsigned short Protected_Payload_Length;
    unsigned short version
}longform;

typedef struct{
    unsigned short Packet_Type;
    unsigned short Unprotected_Payload_Length;
    union u{
        longform l;
        unsigned short version;
    };
} PKT_HEADER;

然后可以使用任何一种方式(同样,取决于Packet_type)对传入的数据进行解码,而剩余空间可以忽略。需要注意的是,不能使用sizeof(PKT_HEADER),因为结构大小将始终是较大的值。

相关问题