struct details_state {
struct details_status D1;
struct details_status D2;
};
struct details {
struct details_state details_states[2];
} __attribute__((packed));
struct details *p;
void print_details_status(struct details_status *s)
print_details_status(&(p->details_states[i].D1));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: taking address of packed member of 'struct details' may result in an unaligned pointer value [-Waddress-of-packed-member]
GCC gives this warning with >9 version. How to get rid of this warning without using [-Wno-address-of-packed-member]
In the comments to your post you have the explanation of the why it warns and why it can be a bad idea to take a pointer of a non-aligned member. The issue is not so much about assigning an unaligned value to a pointer (which seems to be permitted by bullet 5 of 6.3.2.3 here, but only about dereferencing it. Dereferencing it seems to be even explicitly permitted on some architectures, albeit with a performance penalty (e.g.: on x86 when not using SSE load/store), but it may cause severe issues depending on type and generated assembly on other architectures, typically a BUS ERROR if you are in user space or a fault if you are in kernel space.
For bad that it may be to do something like that, there is code around that takes pointers of packed struct's elements and even dereferences them without shame: https://github.com/abperiasamy/rtl8812AU_8821AU_linux/blob/4d1726146fd96552c9fa5af05c75187027d6885b/core/rtw_cmd.c#L1481 https://github.com/abperiasamy/rtl8812AU_8821AU_linux/blob/4d1726146fd96552c9fa5af05c75187027d6885b/core/rtw_mlme.c#L3689
I can imagine that someone may be in a situation where they are stuck with someone else's code with a packed struct (note that it would be bad to have a packed struct in a library's header file, as packing is a non-standard extension to the language and its results are compiler dependent). Or maybe they have a function that is guaranteed to deal properly with an unaligned pointer; as the C standard provides no way to communicate that in the code, one would have to rely on the function's documentation (and/or implementation) to figure that.
Now that you understand what's wrong with it but also that it can sometimes be useful to suppress that warning locally without setting a global compiler option; here's an answer to:
You can use the base address to the struct and add to it the relevant offset, obtained via
offsetof(). This requires some casting and, even turned into a macro, it is not particularly clean as it requires several arguments:This can be simplified so you don't have to pass the
elementType, but then the return value of the macro will be avoid*which means compiler warnings may get suppressed when you mistakenly pass it to a function that expects a pointer to something else than the type of thememberNameelement, so I wouldn't recommend this:If your compiler supports the non-standard
typeof()(e.g.: this is provided bystddef.hingcc), you can simplify the macro so that no type has to be passed, the returning pointer's type is still correct and the code using it becomes simpler and less error-prone:Example code: