Search code examples
cunionstype-punning

Type punning pointers via union


Can I use type punning with union members which are pointer to signed and unsigned versions of a type? For example, is the following usage of p.u guaranteed to work by the standard?

void foo(unsigned *u);

int num = 7;
union
{
    int *i;
    unsigned *u;
} p;

p.i = #

foo(p.u);

Assuming that num is non-negative it seems it should be fine on most platforms. I'm wondering whether it's guaranteed that the two pointers will have the same representation in memory?


Solution

  • There are very strictly speaking no guarantees that these two pointer types have the same representation in memory. The C standard only guarantees that (6.3.2.3) "A pointer to an object type may be converted to a pointer to a different object type." /--/ "Otherwise, when converted back again, the result shall compare equal to the original pointer."

    To satisfy this requirement in practice, it is however extremely likely that int* and unsigned* have the same representation in memory. To the point where I wouldn't worry about it.

    The type punning itself is otherwise well-defined (6.2.6), as is accessing an object of effective type int through an unsigned int*, or an object of effective type unsigned int through a int* (6.5/7 "strict aliasing").

    The real question here is why you'd use such a union instead of always accessing the memory by an unsigned int* and then cast the de-referenced value to int when needed.