mercredi 3 août 2022

C++: derived structure layout and copiability

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 memcpyd 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