通过 std::bit_cast()ed 指针进行别名访问

问题描述 投票:0回答:1

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

reinterpret_cast
转换为结构指针。

C++

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 的对象表示,则返回值未指定。

那么,不同的指针表示形式不兼容、无法相互对应的情况下,符合标准的编译器是否可能存在?

c++ language-lawyer c++20 strict-aliasing
1个回答
3
投票

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

你如何获得这些指针基本上是无关紧要的。所以在这方面

bit_cast
并不比
reinterpret_cast
好。

如果那里没有

sockaddr_in
,那么你就不能假装有一个。但是,C++20 中的“隐式对象创建”可能已经解决了这个问题,具体取决于您的代码。如果确实如此,那么您如何获取指针仍然并不重要。

© www.soinside.com 2019 - 2024. All rights reserved.