Violating strict-aliasing rules yields undefined behavior, e.g. when sending a struct over the network into a char buffer, and then that char pointer is C-style/reinterpret_cast
casted to a struct pointer.
The C++ std::bit_cast()
function looks like it could be used to cast such pointers in an (implementation?) defined way, i.e. without violating strict-aliasing rules.
Example:
#include <sys/types.h>
#include <netinet/in.h>
#include <bit>
int get_sock_addr(const struct sockaddr *a)
{
struct sockaddr_in *x = std::bit_cast<struct sockaddr_in*>(a);
return x->sin_addr.s_addr;
}
So the caller of get_sock_addr()
somehow obtained a sockaddr
pointer and has determined that it actually points to a sockaddr_in
struct.
So, is such pointer casting via std::bit_cast()
a valid use-case?
Or does it somehow yield undefined behavior, as well?
If it's defined behavior, does the standard classify such pointer-casting as implementation-defined behavior?
The std::bit_cast()
proposal mentions:
If no value representation corresponds to To's object representation then the returned value is unspecified.
So is a standard-conforming compiler possible where different pointer representations are incompatible such that they can't correspond to each other?
Converting the pointer value is irrelevant. What matters is the object. You have a pointer to an object of type X, but the pointer's type is Y. Trying to access the object of type X through a pointer/reference to unrelated type Y is where the UB comes from.
How you obtained those pointers is mostly irrelevant. So bit_cast
is no better than reinterpret_cast
in this regard.
If there is no sockaddr_in
there, then you can't pretend that there is one. However, it's possible that implicit object creation in C++20 already solves this matter, depending on your code. If it does, then it still doesn't matter how you get the pointer.