违反严格别名规则会产生未定义的行为,例如当通过网络将结构发送到 char 缓冲区时,然后该 char 指针是 C 风格/
reinterpret_cast
转换为结构指针。
std::bit_cast()
函数看起来可以用来以(实现?)定义的方式转换此类指针,即不违反严格别名规则。
示例:
#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;
}
因此
get_sock_addr()
的调用者以某种方式获得了 sockaddr
指针,并确定它实际上指向 sockaddr_in
结构体。
那么,这种通过
std::bit_cast()
进行的指针转换是一个有效的用例吗?
或者它是否也会以某种方式产生未定义的行为?
如果是定义的行为,标准是否将此类指针转换归类为实现定义的行为?
std::bit_cast()
提案提到:
如果没有值表示对应于 To 的对象表示,则返回值未指定。
那么,不同的指针表示形式不兼容、无法相互对应的情况下,符合标准的编译器是否可能存在?
转换指针值是无关紧要的。重要的是对象。你有一个指向 X 类型对象的指针,但该指针的类型是 Y。尝试通过对不相关类型 Y 的指针/引用来访问类型 X 的对象是 UB 的来源。
你如何获得这些指针基本上是无关紧要的。所以在这方面
bit_cast
并不比reinterpret_cast
好。
如果那里没有
sockaddr_in
,那么你就不能假装有一个。但是,C++20 中的“隐式对象创建”可能已经解决了这个问题,具体取决于您的代码。如果确实如此,那么您如何获取指针仍然并不重要。