This question followes this one
让我们考虑一下这个示例代码:
struct sso
{
union{
struct {
char* ptr;
char size_r[8];
} large_str;
char short_str[16];
};
bool is_short_str() const{
return *std::launder(short_str+15)=='\0'; //UB?
}
};
If short_str
不是活动成员在没有取消引用指针的情况下std::launder
将是UB。让我们考虑一下 ABI 已明确指定,并且我们知道 size_r[7] 与 Short_str[15] 位于同一地址。做std::launder(short_str+15)
返回一个指向size_r[7]
when short_str
不是工会的活跃成员吗?
注:我认为情况是这样的,因为[ptr.launder]/3
存储字节可通过指向对象 Y 的指针值访问,如果该指针值位于 Y 占用的存储空间内,则该对象 Y 位于 Y 占用的存储空间内,或者是可与 Y 指针相互转换的对象,或者如果 Y 是数组元素则指向直接封闭的数组对象。
让我们考虑 ABI 已明确指定,并且我们知道 size_r[7] 与 Short_str[15] 位于同一地址
这完全取决于该保证的确切含义。
编译器可以自由地保证
Sso.short_str[15]
可以访问和修改一切,即使Sso.large_str
当前处于活动状态,并且完全获得您期望的语义。
或者不提供这种保证也是自由的。
对于格式错误或表现出未定义行为的行为或程序没有任何限制。
由于那里没有任何物体,&Sso.short_str[15]
不能与任何东西进行指针互换。不存在的对象不具有与另一个对象“相同的地址”。
Launder 是根据指向预先存在的对象的指针来定义的。然后该指针被销毁,并创建一个具有相同地址的新对象(这是明确定义的)。std::launder
then 让您获取指向不再存在的对象的指针并获取指向现有对象的指针。
你正在做的事情不是那样的。如果你拿了&short_str[15]
当它was订婚后,您将拥有一个指向对象的指针。 ABI 可以说该地址与size_r[7]
。现在std::launder
将在有效性范围内。
但编译器可以更进一步并定义它short_str[15]
指的是同一个对象size_r[7]
即使它不活跃。
我认为与你的内容一致的最弱的 ABI 保证只有在你获取了地址时才有效short_str[15]
当它处于活动状态时;稍后,您将参与large_str
,然后你可以从&short_str[15]
to &size_r[7]
。与您的陈述一致的最强有力的 ABI 保证要求std::launder
不需要。在中间的某个地方std::launder
将被要求。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)