【问题标题】:reinterpret_cast and explicit alignment requirementreinterpret_cast 和明确的对齐要求
【发布时间】:2021-12-17 15:38:16
【问题描述】:

鉴于reinterpret_cast 的这个(粗体部分),我期待下面的代码在将X* 转换为Y* 时会生成不同的地址,因为后者比前者更严格对齐。我在这里错过了什么?

任何对象指针类型 T1* 都可以转换为另一个对象指针类型 cv T2*。这完全等价于 static_cast(static_cast(expression)) (这意味着如果 T2 的对齐要求不比 T1 严格,则指针的值不会改变 并将结果指针转换回其原始类型会产生原始值)

cppreference/reinterpret_cast

#include <iostream>


struct alignas (1) X
{
    char c;
};


struct  alignas (32) Y
{
    char c;
};

int main(int argc, const char *const* const argv)
{
    std::cout << alignof(X) << " " << alignof(Y) << std::endl;

    X x;
    Y y;
    std::cout << &x << " " << reinterpret_cast<Y*>(&x) << std::endl;
    std::cout << &y << " " << reinterpret_cast<X*>(&y) << std::endl;

}

输出

Program returned: 0
1 32
0x7ffef3434578 0x7ffef3434578
0x7ffef3434540 0x7ffef3434540

snippet on godbolt

【问题讨论】:

  • “如果 a 那么 b”并不意味着“如果不是 a 那么不是 b”
  • 来自static_cast 参考:"如果原始指针值表示内存中不满足目标类型对齐要求的字节地址,那么得到的指针值为未指定。”我相信这条规则适用于此。请参阅en.cppreference.com/w/cpp/language/static_cast 中的 10)。 C++ 标准(草案)链接:eel.is/c++draft/expr.static.cast#13.sentence-2.
  • @463035818_is_not_a_number 感谢您的一般回答。我期待标准中提供更多上下文的东西。
  • 重新解释强制转换永远不会改变指针的二进制值。它只解释它的类型
  • @RbMm 问题中的引用不同意。

标签: c++ alignment reinterpret-cast


【解决方案1】:

引用[expr.reinterpret.cast]/7:

对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvaluev转换为对象指针类型“pointer to cv T”时,结果为static_­cast&lt;cv T*&gt;(static_­cast&lt;cv void*&gt;(v))

那么,来自[expr.static.cast]/13

类型“指向 cv1 void”的纯右值可以转换为类型“指向 cv2 T”的纯右值,其中T 是对象类型,而 cv2 与 cv-qualification 相同,或比 cv1 更高的 cv 资格。 如果原始指针值表示内存中某个字节的地址A,而A不满足T的对齐要求,则结果指针值未指定....

我相信这些规则在这里适用。在您的情况下,reinterpret_cast&lt;Y*&gt;(&amp;x) 被解析为static_cast&lt;Y*&gt;(static_cast&lt;void*&gt;(&amp;x))原始指针值static_cast&lt;void*&gt;(&amp;x)代表地址A,这个地址一般不满足Y的对齐要求。 因此,结果指针的值是未指定

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多