Reputation: 4050
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
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
.
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.
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 tovoid
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