我需要创建一个带有可选值的结构:
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在这种情况下不存在。
我是否必须以数据格式声明适当的结构,或者还有其他方法可以使用这些结构?
感谢您的帮助。
答案 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)
,因为结构大小将始终是较大的值。