C++ 通过std::bit_cast()带别名的指针进行别名访问

C++ 通过std::bit_cast()带别名的指针进行别名访问,c++,language-lawyer,c++20,strict-aliasing,C++,Language Lawyer,C++20,Strict Aliasing,违反严格的别名规则会产生未定义的行为,例如,当通过网络将结构发送到char缓冲区时,然后该char指针是C-style/std::reinterpret_cast()cast到结构指针 C++看起来像可以用(实现)定义的方式来抛出这些指针,即不违反严格的混叠规则。 例如: #include <sys/types.h> #include <netinet/in.h> #include <bit> int get_sock_addr(const struct

违反严格的别名规则会产生未定义的行为,例如,当通过网络将结构发送到char缓冲区时,然后该char指针是C-style/
std::reinterpret_cast()
cast到结构指针

C++看起来像可以用(实现)定义的方式来抛出这些指针,即不违反严格的混叠规则。 例如:

#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;
}
#包括
#包括
#包括
int get_sock_addr(const struct sockaddr*a)
{
结构sockaddr_in*x=std::bit_cast(a);
返回x->sin\u addr.s\u addr;
}
因此,
get\u sock\u addr()
的调用者不知何故获得了一个
sockaddr
指针,并确定它实际上指向了结构中的
sockaddr\u

那么,通过
std::bit_cast()
这样的指针转换是有效的用例吗

或者它是否也会产生未定义的行为

如果是定义的行为,标准是否将此类指针转换分类为实现定义的行为


报告提到:

如果没有值表示形式对应于的对象表示形式,则返回的值未指定


那么,如果不同的指针表示不兼容,以致于它们不能相互对应,那么标准一致性编译器是否可能呢?

转换指针值是不相关的。重要的是目标。您有一个指向类型为X的对象的指针,但该指针的类型为Y。试图通过指向不相关类型Y的指针/引用访问类型为X的对象是UB的来源

你是如何获得这些指针的,这基本上是无关紧要的。因此,在这方面,
bit\u cast
并不比
reinterpret\u cast
好多少


如果那里没有
sockaddr\u,那么你就不能假装有。然而,在C++20中可能已经解决了这个问题,这取决于您的代码。如果是这样,那么如何获取指针仍然无关紧要。

您的示例及其假设是
reinterpret\u cast的标准有效用例
@DavisHerring hm,这实际上取决于调用示例get\u sock\u addr函数之前/之后对sockaddr指针所做的操作,对吗?例如,使用类似于
sockaddr*a=getfromsomewhere()的东西;如果(a->sa_family==AF_INET)addr=get_sock_addr(a);…}
sockaddr\u in对象是通过两个类型的别名指针访问的,这些类型的指针不受严格的别名规则的限制,对吗?在问题中,您只是说“它实际上指向
sockaddr\u in
struct”。您刚才给出的代码试图验证该假设,但实际上与之不兼容(不幸的是,因为这是传统C接口的设计方式)。常见的初始子序列规则旨在允许这种标记,但它们需要实际的并集。@DavisHerring在问题中,我说调用方“已确定它实际上指向结构中的sockaddr_”。因此,我在最后的评论中给出的代码是这个确定步骤的一个可能实现。当然,在最初的示例代码中包含这一步骤,对于问题的目的来说,可以说是一个更好的示例。我们达成了一致。该代码是确定隐藏在指针后面的实际类型的明显方法,但是C++不允许您这样做,因为它涉及使用对象作为不同类型来做出非常确定。我想知道为什么在C++11标准文档中找不到C有效类型的概念。