阅读 this answer 中关于严格别名规则的引用,我看到 C++11 的以下内容:
所以我认为下面的代码没有违反严格的别名规则:
#include <iostream>
#include <cstdint>
#include <climits>
#include <limits>
struct PunnerToUInt32
{
std::uint32_t ui32;
float fl;
};
int main()
{
static_assert(std::numeric_limits<float>::is_iec559 &&
sizeof(float)==4 && CHAR_BIT==8,"Oops");
float x;
std::uint32_t* p_x_as_uint32=&reinterpret_cast<PunnerToUInt32*>(&x)->ui32;
*p_x_as_uint32=5;
std::cout << x << "\n";
}
好了,满足严格的别名规则。这是否仍然出于任何其他原因表现出未定义的行为? 最佳答案
你不能这样做:&reinterpret_cast<PunnerToUInt32*>(&x)
reinterpret_cast
状态的规则:
因为对于 DynamicType
是 float
和 AliasedType
是 PunnerToUInt32
的组合,这些都不是真的,所以指针可能不会用于访问您正在执行的对象。使行为未定义。
有关更多信息,请参阅:Why Doesn't reinterpret_cast Force copy_n for Casts between Same-Sized Types?
编辑:
分解第 4 个子弹 int 大小的块会产生:
AliasedType
"这里取PunnerToUInt32
PunnerToUInt32
符合条件,因为它符合 aggregate type 的条件:PunnerToUInt32
有资格,因为它是 float fl
成员 AliassedType
是一个 PunnerToUInt32
DynamicType
的 x
不是 PunnerToUInt32
因为违反第 5 部分对该指针的操作是未定义的行为。
如果您关心一些推荐阅读,您可以查看 Empty Base Optimization 如果不是,我将在这里为您提供主要相关性:
因此,您可以通过执行以下操作来利用
reinterpret_cast
的第 4 个项目符号:PunnerToUInt32 x = {13, 42.0F};
auto y = reinterpret_cast<PunnerToUInt32*>(&x.ui32);
关于c++ - 这种双关语定义明确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38000599/