"Misalignment" of a structure member can only occur if the alignment requirements of the structure member are deliberately hidden. (Or if some implementation-specific mechanism is used to suppress alignment, such as gcc's packed
attribute`.)
For example, in the referenced problem, the issue is that there is a struct:
struct {
// ... stuff
int val;
unsigned char data[DATA_SIZE];
// ... more stuff
}
and the programmer attempts to use data
as though it were a size_t
:
*(size_t*)s->data
However, the programmer has declared data
as unsigned char
and the compiler therefore only guarantees that it is aligned for use as an unsigned char
.
As it happens, data
follows an int
and is therefore also aligned for an int
. On some architectures this would work, but on the target architecture a size_t
is bigger than an int
and requires a stricter alignment.
Obviously the compiler cannot know that you intend to use a structure member as though it were some other type. If you do that and compile for an architecture which requires proper alignment, you are likely to experience problems.
The referenced thread suggests inserting a zero-length size_t
bit-field before the declaration of the unsigned char
array in order to force the array to be aligned for size_t
. While that solution may work on the target architecture, it is not portable and should not be used in portable code. There is no guarantee that a 0-length bit-field will occupy 0 bits, nor is there any guarantee that a bit-field based on size_t
will actually be stored in a size_t
or be appropriately aligned for any non bit-field use.
A better solution would be to use an anonymous union:
// ...
int val;
union {
size_t dummy;
unsigned char data[DATA_SIZE];
};
// ...
With C11, you can specify a minimum alignment explicitly:
// ...
int val;
_Alignas(size_t) unsigned char data[DATA_SIZE];
// ...
In this case, if you #include <stdalign.h>
, you can spell _Alignas
in a way which will also work with C++11:
int val;
alignas(size_t) unsigned char data[DATA_SIZE];