[Image-SIG] rehash_collide, strict aliasing, and pointer sizes

Brian Crowell brian at fluggo.com
Sun Oct 14 05:56:05 CEST 2012


I'm trying to iron out some of the strict-aliasing warnings that come
up when building the code under Python 3. (Strict aliasing is a C rule
against using the same pointer as two different types, which, when
followed, gives the optimizer a huge advantage. This didn't come up
under Python 2, because Python 2 code couldn't be built with strict
aliasing on, so it becomes an issue in Python 3 code where strict
aliasing is on by default.)

I came across this strange function in Quant.c:

static void
rehash_collide(HashTable h,
               void **keyp,
               void **valp,
               void *newkey,
               void *newval)
{
    *valp=(void *)((*(int *)valp)+(*(int *)&newval));
}

This function sets off red flags in my brain. It's essentially casting
two void pointers to ints to add them and then cast them back.

Now, the strict-aliasing-safe version is not hard to write:

static void
rehash_collide(HashTable h,
               void **keyp,
               void **valp,
               void *newkey,
               void *newval)
{
    union {
        void *ptr;
        int val;
    } uresult, uvalp = { *valp }, unewval = { newval };

    uresult.val = uvalp.val + unewval.val;
    *valp = uresult.ptr;
}

...but the fact that it equates the sizes of ints and void pointers
worries me. Is there a good reason this function isn't written:

static void
rehash_collide(HashTable h,
               void **keyp,
               void **valp,
               void *newkey,
               void *newval)
{
   *valp=(void *)(((size_t) *valp) + ((size_t) newval));
}

...?

--Brian


More information about the Image-SIG mailing list