What are the strict aliasing rules when casting *f

2019-04-28 20:58发布

问题:

I'm confused by the strict aliasing rules when it comes to casting a char array to other types. I know that it is permitted to cast any object to a char array, but I'm not sure what happens the other way around.

Take a look at this:

#include <type_traits>

using namespace std;

struct{
    alignas (int) char buf[sizeof(int)]; //correct?
} buf1;

alignas(int) char buf2[sizeof(int)]; //incorrect?

struct{
    float f; //obviously incorrect
} buf3;

typename std::aligned_storage<sizeof(int), alignof(int)>::type buf4; //obviously correct

int main()
{
    reinterpret_cast<int&>(buf1) = 1;
    *reinterpret_cast<int*>(buf2) = 1;
    reinterpret_cast<int&>(buf3) = 1;
    reinterpret_cast<int&>(buf4) = 1;
}

Compiling using g++-5.3.0 results in warnings only on the second and third line of main:

$ g++ -fsyntax-only -O3 -std=c++14 -Wall main.cpp 
main.cpp: In function ‘int main()’:
main.cpp:25:30: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  *reinterpret_cast<int*>(buf2) = 1;
                              ^
main.cpp:26:29: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  reinterpret_cast<int&>(buf3) = 1;
                             ^

Is gcc correct in that lines 1 and 4 are correct, while lines 2 and 3 are not? I'm fairly sure line 4 is correct (that's what aligned_storage is for), but what are the rules at play here?

回答1:

First of all, absence of warning is not a guarantee of correctness! gcc is getting better and better at spotting problematic code, but it is still not a static analyzing tool (and those are not perfect either!)

Second of all, yes, you are not allowed to access char array through a pointer to other type.