Search code examples
c++serializationalignmentpacked

How to properly access packed struct members


What is the correct way to access packed struct's members?

struct __attribute__ ((packed)) MyData {
    char ch;
    int i;
}
void g(int *x); // do something with x

void foo(MyData m) {
    g(&m.i);
}

void bar(MyData m) {
    int x = m.i;
    g(&x);
}

My IDE gives warning/suggestion for foo that I might be accessing misaligned int pointer, which is indeed the case here. My questions are

  • Between foo and bar, is one approach better than the other?
  • Is it incorrect to access misaligned pointer data but okay to use it to initialize a properly aligned type? (as in bar).
  • Should we copy packed struct individual members to properly aligned data structure and then use it? That would imply that for almost every packed data structure there is a non-packed data structure and packed structure remains confined to serialization layer.

Solution

  • Is it incorrect to access misaligned pointer data but okay to use it to initialize a properly aligned type? (as in bar).

    As far as the C++ language is concerned, there is no such thing as a packed class nor such thing as improperly aligned object. Hence, an improperly aligned pointer would necessarily be invalid.

    Whether your compiler that provides a language extension for packed classes also extends the language to allow access through misaligned pointers is up for your compiler vendor to document. The warning implies that latter extension might not be supported.

    Between foo and bar, is one approach better than the other?

    bar, as per the warning.

    Should we copy packed struct individual members to properly aligned data structure and then use it? That would imply that for almost every packed data structure there is a non-packed data structure and packed structure remains confined to serialization layer.

    That could be a convenient solution to confine the non-standard packed classes into the serialisation layer.

    Note that this isn't the only problem with packed structs. Another problem is portability of serialised data between systems due to different byte orders and sizes of types.

    A portable way to serialise data is to not use packed structs at all, but rather shift bytes individually using explicit offsets.