fieldtensor
fieldtensor

Reputation: 4050

Does dynamic type choice break strict aliasing in C?

Let's say that I have some code that looks like this:

void foo(void* obj, int type)
{
    TypeA* a = (TypeA*)obj;
    TypeB* b = (TypeB*)obj;
    TypeC* c = (TypeC*)obj;

    if( type == 1 ) {
        // code that uses "a"
    }
    else if( type == 2 ) {
        // code that uses "b"
    }
    else if( type == 3 ) {
        // code that uses "c"
    }
}

I'm curious to know whether or not this function breaks strict aliasing a priori, or if the validity of the function depends on how it's actually used. A certain part of me wants to hope that things will work out fine if I only ever used the function as foo(&objectOfTypeA, 1), foo(&objectOfTypeB, 2), or foo(&objectOfTypeC, 3). Yet I've only know about aliasing errors for a few days, and so I worry that the function foo() is broken right from the start simply because it casts the incoming void* to various different types to begin with.

Upvotes: 4

Views: 84

Answers (1)

Dietrich Epp
Dietrich Epp

Reputation: 213368

This does not break strict aliasing, because you only access *obj through the correct type. Casting obj does not result in access to *obj.

The strict aliasing rule

Strict aliasing only applies to accessing an object, not to pointer manipulations. You can manipulate the pointer all you want.

From n1570 §6.5 ¶7

An object shall have its stored value accessed only by an lvalue expression that has one of the following types...

Since you're not accessing *obj but just obj, the strict aliasing rule is not violated.

Conversions

The second question here is whether the conversions are permissible. The answer is yes, because you can convert a void * to any other object pointer type. The void type is special, it is the only type with this property.

int *i;
void *ptr = &i;
float *f = ptr; // Permissible

The standard is silent on what the value of f is. In other words, while the conversion is permissible, there is nothing useful you can do with f. You can't even convert it back to void *.

This is explained in n1570 §6.3.2.3 ¶1:

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again, the result shall compare equal to the original pointer.

So, to repeat, the conversion is always permissible but not useful in any way.

Upvotes: 3

Related Questions