【问题标题】:Conversion between long* and int* when sizeof(long) == sizeof(int)当 sizeof(long) == sizeof(int) 时 long* 和 int* 之间的转换
【发布时间】:2014-05-23 12:47:54
【问题描述】:

我们一般都知道sizeof(long) != sizeof(int)。但是 (C++11) 标准的哪些部分不允许别名 long*int*?仅仅是[conv.ptr]中的省略,[basic.lval]中的别名规则,还是其他什么?

void f()
{
    static_assert(sizeof(int) == sizeof(long), "");
    long x[] = {1, 2};
    int* y = x; // error: invalid conversion from ‘long int*’ to ‘int*’ [-fpermissive]
}

【问题讨论】:

    标签: c++ c++11 type-conversion language-lawyer type-punning


    【解决方案1】:

    是的,这是[conv.ptr]中的省略,适用的段落在[expr.reinterpret.cast]中,

    7 对象指针可以显式转换为对象指针 一种不同的类型。当类型为“指向 T1 的指针”的纯右值 v 是 转换为“指向 cv T2 的指针”类型,结果为 static_cast<cv T2*>(static_cast<cv void*>(v)) 如果 T1 和 T2 都是 标准布局类型 (3.9) 和 T2 的对齐要求是 不比 T1 更严格,或者如果任一类型为 void。转换一个 “指向 T1 的指针”类型的纯右值到类型“指向 T2 的指针”(其中 T1 和 T2 是对象类型,其中 T2 的对齐要求是 不比 T1 更严格)并返回其原始类型产生 原始指针值。任何其他此类指针的结果 转换未指定。

    你必须使用reinterpret_cast<int*>(...)


    编辑。 我在此编辑中使 cmets 更加明显,这不是语言律师问题,而是意图使用指针。我不确定这个问题是如何产生的,因为很明显,一个人可以简单地进行 C-cast 而无需询问,但如果有疑问 - 指向 int* 的指针违反了 strict aliasing 规则。

    也就是说,未定义的行为可能是由于您打破了编译器的假设,即不同类型的指针永远不会指向相同的内存位置。

    【讨论】:

    • 这会导致编译错误,但是即使使用了正确的强制转换,由于违反了别名规则,它仍然是未定义的行为。
    • @BenVoigt Nitpick:我读到“未指定”,它是在没有强制性文档的情况下定义的实现。
    • @peter 你没有看到严格的别名规则。
    • @BenVoigt 这是真的。我该去哪里看?在标准中快速搜索似乎没有产生相关结果。
    • @Peter 有一个关于 SO 的常见问题解答,标题为什么是强别名规则,另请参阅其他答案。
    【解决方案2】:

    longint是两种不同的类型,即使它们大小相同,所以我认为无效转换是由于[basic.lval.10]

    如果程序尝试通过以下方式访问对象的存储值 行为是以下类型之一以外的泛左值 未定义:

    • 对象的动态类型,
    • 对象动态类型的 cv 限定版本,
    • 与对象的动态类型类似(如 4.4 中定义)的类型,
    • 对应于动态类型的有符号或无符号类型 对象,
    • 一种有符号或无符号类型,对应于对象动态类型的 cv 限定版本,
    • 包含上述类型之一的聚合或联合类型 在其元素或非静态数据成员(包括, 递归地,子聚合的元素或非静态数据成员或 包含联合),
    • 一种类型,它是对象动态类型的(可能是 cv 限定的)基类类型,
    • char 或 unsigned char 类型。

    附带说明,如果 [basic.lval] 不存在,还会有其他问题:相同的大小并不意味着相同的表示/范围。

    无法保证int 中的值位与long 中的值位精确对应。

    【讨论】:

    • 代表的东西是红鲱鱼。优化器将假定没有别名。
    • @BenVoigt 是的,你是对的。表示的东西现在是一个旁注。谢谢。
    猜你喜欢
    • 2013-09-24
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2021-06-09
    • 2013-02-19
    • 1970-01-01
    相关资源
    最近更新 更多