[ACCEPTED]-dereferencing type-punned pointer will break strict-aliasing rules" warning-strict-aliasing

Accepted answer
Score: 61

In order:

  • Yes. GCC will assume that the pointers 24 cannot alias. For instance, if you assign 23 through one then read from the other, GCC 22 may, as an optimisation, reorder the read 21 and write - I have seen this happen in production 20 code, and it is not pleasant to debug.

  • Several. You 19 could use a union to represent the memory 18 you need to reinterpret. You could use a 17 reinterpret_cast. You could cast via char * at the point where 16 you reinterpret the memory - char * are defined 15 as being able to alias anything. You could 14 use a type which has __attribute__((__may_alias__)). You could turn off 13 the aliasing assumptions globally using 12 -fno-strict-aliasing.

  • __attribute__((__may_alias__)) on the types used 11 is probably the closest you can get to disabling 10 the assumption for a particular section 9 of code.

For your particular example, note 8 that the size of an enum is ill defined; GCC 7 generally uses the smallest integer size 6 that can be used to represent it, so reinterpreting 5 a pointer to an enum as an integer could 4 leave you with uninitialised data bytes 3 in the resulting integer. Don't do that. Why 2 not just cast to a suitably large integer 1 type?

Score: 13

You could use the following code to cast 1 your data:

template<typename T, typename F>
struct alias_cast_t
{
    union
    {
        F raw;
        T data;
    };
};

template<typename T, typename F>
T alias_cast(F raw_data)
{
    alias_cast_t<T, F> ac;
    ac.raw = raw_data;
    return ac.data;
}

Example usage:

unsigned int data = alias_cast<unsigned int>(raw_ptr);
Score: 11

But why are you doing this? It will break 4 if sizeof(foo) != sizeof(int). Just because 3 an enum is like an integer does not mean 2 it is stored as one.

So yes, it could generate 1 "potentially" wrong code.

Score: 5

Have you looked into this answer ?

The strict aliasing 4 rule makes this setup illegal, two unrelated 3 types can't point to the same memory. Only char* has this privilege. Unfortunately 2 you can still code this way, maybe get 1 some warnings, but have it compile fine.

Score: 3

Strict aliasing is a compiler option, so 6 you need to turn it off from the makefile.

And 5 yes, it can generate incorrect code. The 4 compiler will effectively assume that foobar and 3 pi aren't bound together, and will assume 2 that *pi won't change if foobar changed.

As already 1 mentioned, use static_cast instead (and no pointers).

More Related questions