Suppose I have a chunk of dynamically allocated data:
void* allocate (size_t n)
{
void* foo = malloc(n);
...
return foo;
}
I wish to use the data pointed at by foo
as a special type, type_t
. But I want to do this later, and not during allocation. In order to give the allocated data an effective type, I can therefore do something like:
void* allocate (size_t n)
{
void* foo = malloc(n);
(void) *(type_t*)foo;
...
return foo
}
As per C11 6.5/6, this lvalue access should make the effective type type_t
:
For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
However, the line (void) *(type_t*)foo;
contains no side effects, so the compiler should be free to optimize it away, and I wouldn't expect it to generate any actual machine code.
My question is: are tricks like the above safe? Does giving the data an effective type count as a side-effect? Or by optimizing away the code, will the compiler also optimize away the choice of effective type?
That is, with the above lvalue access trick, if I now call the above function like this:
int* i = allocate(sizeof(int));
*i = something;
Does this cause strict aliasing violation UB as expected, or is the effective type now int
?
The phrase from the standard that you are citing clearly only states something about the access to the object. The only changes to the effective type of the object that the standard describes are the two phrases before that, that clearly describe that you have to store into the object with the type that you want to make effective.
6.5/6
If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value.