I have the following struct:
typedef struct __attribute__ ((__packed__))
{
uint16_t a;
uint32_t b;
} st_t;
-> the "b" member is unaligned.
When I do the following, gcc raises a warning:
st_t st;
uint32_t * b_p = &st.b;
*b_p = 0;
warning log:
taking address of packed member of 'struct <anonymous>' may result in an unaligned pointer value
But when I do the following, It does not raise any warning:
st_t st;
st_t * st_p = &st;
st_p->b = 0;
I don't understand why it does not raise a warning in the second case, since I am still accessing an unaligned member.
Can't provide a standard quote, so someone else will surely write a better answer, but here's a short one.
For a packed struct, from the very definition of what a "packed struct" is, compiler has to generate working machine code for any member access. Unaligned access is known and will be handled appropriately for the CPU.
Pointer to int, however, is assumed to point to a valid int, which may mean it has to be aligned (or there will be "bus error" or some such). Compiler generating valid unaligned access machine code for every int pointer dereference would be quite inefficient on CPUs where it matters, so compiler basically has to make this assumption.
So, if compiler notices a pointer to unaligned address, it rightfully warns, because it is illegal operation on some CPUs, and it may be slower than aligned access even if it is legal. It won't warn for packed struct, because programmer explocitly says "this is unaligned, deal with it" by making the struct packed.