Strict aliasing rule in array

417 Views Asked by At

Is this fragment of code a violation of strict aliasing rule:

int main()
{
    short tab[] = {1,2,3,4};
    int* ps = (int*)(&tab[0]);
    int i = *ps;
}

I do know that if this was in the opposite way it would be a violation

int main()
{
    int tab[] = {1,2,3,4};
    short* ps = (short*)(&tab[0]);
    short s = *ps;
}
3

There are 3 best solutions below

2
On BEST ANSWER

Of course that violates strict aliasing. The code is accessing values through a pointer of a different type, and it isn't char*.

int main()
{
    short tab[] = {1,2,3,4};
    int* ps = (int*)(&tab[0]);
    *ps = 3;
    if(tab[0] == 1) return 1;
    return 0;
}

The code is allowed to return 1 there. Because a write to *ps is a write to an int and according to strict aliasing rules an int pointer cannot possibly point to a short. Therefore the optimizer is allowed to see that the tab array is not modified, optimize out the if statement because it is always true, and rewrite the entire function to simply return 1.

3
On

You'll get undefined behaviour in both cases if you attempt to dereference the converted pointer.

Informally, this is because the alignments of the types might be different.

Using a union; with a longer type and an array of the shorter type is one safe way of converting data.

0
On

Casting a pointer to another (arbitrary) pointer type, as long as it's not ill-formed, doesn't constitute a violation; But accessing the pointees value after dereferencing that pointer would be.

Your cast is equivalent to a reinterpret_cast, [expr.reinterpret.cast]/7:

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void.