I have the following structs
#pragma pack(push)
struct COMMON {
uint16_t type;
uint16_t m;
uint16_t o;
uint16_t f;
uint64_t s;
};
#pragma pack(pop)
#pragma pack(push)
struct A_HEADER : public COMMON {
uint16_t g;
uint16_t c;
};
#pragma pack(pop)
#pragma pack(push)
struct B_HEADER : public COMMON {
uint32_t r;
uint32_t h;
};
#pragma pack(pop)
now I know that the A_HEADER
and B_HEADER
are trivially copyable but are not standard layout. As far as I know, the former property means that they can be memcpy
d safely, while the latter means that there is no guaranteed byte representation for those tho structs.
Now I need to send remotely (via UDP) both A_HEADER
and B_HEADER
. When the receiver got the message in some buffer, it does not know whether it is A_HEADER
or B_HEADER
and have to decide how to decode it depending on the field type
contained on the COMMON
.
In the receiver machine I was thinking something like
void print_header(const uint8_t* buf)
{
const COMMON* com = reinterpret_cast<const COMMON*>(buf)
switch (com->type) {
case A_TYPE:
print_acq_details(reinterpret_cast<const A_HEADER*>(com));
break;
case B_TYPE:
print_cal_details(reinterpret_cast<const B_HEADER*>(com));
break;
}
}
but I have a sort of dissonance in my mind: according to the fact that both structs are trivially copyable and that a base pointer can point to some base-derived class it seems to me that what I wrote is safe; on the other side the fact that the derived struct above are not standard layout makes me worry. Perhaps, since the layout is compiler dependent, I was thinking that everything works as far as I have exactly same compiler on both machines (which have the same architecture).
What is the correct reasoning (if any)?
NOTICE
I know one solution would be to incapsulate COMMON
inside A_HEADER
and B_HEADER
, in such a way to obtain POD, but I cannot modify such part of code.
Aucun commentaire:
Enregistrer un commentaire