I recently came across the strict aliasing rule, but I'm having trouble understanding how to use void *
to perform type punning without breaking the rule.
I know this breaks the rule:
int x = 0xDEADBEEF;
short *y = (short *)&x;
*y = 42;
int z = x;
And I know that I can safely use a union in C99 for type-punning:
union{
int x;
short y;
} data;
data.x = 0xDEADBEEF;
data.y = 42;
int z = data.x;
But how do I use void *
to safely perform type-punning in C99? Is the following correct:
int x = 0xDEADBEEF;
void * helper = (void *)&x;
short *y = (short *)helper;
*y = 42;
int z = x;
I suspect that code will still break the strict aliasing rule since the memory at variable x
's address can be modified by both x
and a dereferenced y
.
If type-punning is undefined via void *
, what is the purpose of the void *
in C99?
void *
has nothing to do with type-punning. Its main purposes are:To allow for generic allocation and freeing operations that don't care about the type of the object the caller is storing there (e.g.
malloc
andfree
).To allow a caller to pass a pointer to an arbitrary type through a function that will pass it back via a callback, (e.g.
qsort
andpthread_create
). In this case, the compiler cannot enforce type checking; it's your responsibility when writing the caller and callback to ensure that the callback accesses the object with the correct type.Pointers to
void
are also used in a few places (likememcpy
) that actually operate on an object as the overlaidunsigned char []
representation for the object. This could be seen as type-punning, but it's not an aliasing violation becausechar
types are allowed to alias anything to access its representation. In this case,unsigned char *
would also work, butvoid *
has the advantage that pointers automatically convert tovoid *
.In your example, since the original type is
int
and not a union, there is no legal way to type-pun and access it asshort
. You could instead copy the value ofx
to a union, perform well-defined type-punning there, then copy it back. A good compiler should omit the copy entirely. Alternatively, you could break the write down intochar
writes and then it would be legal aliasing.