I have a bunch of code taking binary blobs from network. On knowing the type of the blob I've so far used type punning (pseudo):
uint8_t* data = network.get();
if(type == "A") {
uint32_t* var = reinterpret_cast<uint32_t*>(data);
...
} else if (type == "B") {
float* var = reinterpret_cast<float*>(data);
...
}
And in some places there are unions:
union A {
float valf;
uint32_t valu;
};
And this would seem to work fine, but now I read posts on type punning like this is UB as per standard and that I should use memcpy instead. Yet, it provably works on many platforms.
Q1: Is there a way to test if type punning is supported and behaves as expected on my platform?
Q2: Can I expect mainstream compilers (MSVC, GCC) to warn or error on illegal type punning on my platform?
Q1: Is there a way to test if type punning is supported and behaves as expected on my platform?
Yes, read the compiler manual. There is usually a chapter about non-standard extensions. For example gcc C extensions or gcc C++ extensions. If there is no documented non-standard extension (or in case you compile for strict standard compliance), you have to assume that using such code is unsafe and undefined behavior.
gcc in particular is traditionally infamous for invoking undefined behavior upon strict pointer aliasing violations. You can block it from exploiting that UB during optimizations with -f-no-strict-aliasing
.
Type punning through unions is well-defined in C but undefined in C++.
Q2: Can I expect mainstream compilers (MSVC, GCC) to warn or error on illegal type punning on my platform?
No, this is very rare. In general, you can't expect diagnostic messages upon invoking undefined behavior. This is why there's still a market for static analyser tools. Also, many forms of undefined behavior occur in run-time.