阅读 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 状态的规则:



因为对于 DynamicTypefloatAliasedTypePunnerToUInt32 的组合,这些都不是真的,所以指针可能不会用于访问您正在执行的对象。使行为未定义。

有关更多信息,请参阅:Why Doesn't reinterpret_cast Force copy_n for Casts between Same-Sized Types?

编辑:

分解第 4 个子弹 int 大小的块会产生:

  • "AliasedType "这里取PunnerToUInt32
  • “是聚合类型或 union 类型” PunnerToUInt32 符合条件,因为它符合 aggregate type 的条件:

  • “将上述类型之一保存为元素或非静态成员(包括递归地,子聚合的元素和所包含 union 的非静态数据成员)”再次 PunnerToUInt32 有资格,因为它是 float fl 成员
  • “这使得获得指向结构或 union 的可用指针变得安全”这是最后正确的部分,因为 AliassedType 是一个 PunnerToUInt32
  • “给定一个指向其非静态成员或元素的指针”这是一个违规行为,因为作为 DynamicTypex 不是 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/

    10-13 09:15