'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 1:[1]

Currently, calling g may assume that x is aligned. This will probably be fine on x86 architectures, but foo might crash on ARM.

Calling it like in bar is not much better than g taking int x. However, it is correct, since the compiler knows that m.i is misaligned, so can generate the code to copy a misaligned int. This does mean that the pointer can't modify the original object (unless you reassign it).

You can also use the type of a misaligned integer:

typedef int __attribute__((aligned(1))) packed_int;
void g(packed_int * x); // do something with x

This can be called directly as g(&m.i). Be warned that it cannot perform aligned access leading to slowdowns on some platforms.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Artyer