There are multiple questions about the warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
, from when adding compiler options -Wstrict-aliasing=2 -fstrict-aliasing
, and how to solve it.
For instance, the most upvoted answer to this Q states that,
(…) gcc assumes that your program will never access variables though pointers of different type.
This assumption is called strict-aliasing and allows the compiler to make some optimizations (…)
When attempting to rewrite (read cast) a struct
as an array (for use in an external API), I found that the warning disapeared when adding an intermediate step of creating a pointer to said struct object, and casting that pointer instead.
I want to know if this is (not safe but) safer than directly casting the struct object (which prompts the warning), or have I just conceiled what I’m doing from the compiler in such a way that the compiler doesn’t see the danger and doesn’t produce the warning? If it is safer, why? I don’t really understand the actual difference.
If it matters, the reinterpret_cast
-ed data will not be accessed: it will be stored/transported and reinterpret_cast
-ed back again to the original struct
before being used.
#include <iostream>
#include <cstdint>
struct Container
{
uint32_t x;
uint32_t y;
};
// SomeApi could for instance have been (from <fcntl>),
// write(some_fd, data, size);
void SomeApi(uint32_t* data, size_t size)
{
for (size_t i=0; i<size; i++)
std::cout << (i==0?"{":", ") << static_cast<unsigned>(data[i]);
std::cout << "}n";
}
int main() {
Container c{3,4};
uint32_t* data = reinterpret_cast<uint32_t*>(&c);
SomeApi(data, sizeof(c)/sizeof(uint32_t));
// warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
Container* p_c = &c;
uint32_t* p_data = reinterpret_cast<uint32_t*>(p_c);
SomeApi(p_data, sizeof(c)/sizeof(uint32_t));
// Seemingly without issues?
return 0;
}