当sizeof(long)== sizeof(int)时,long *和int *之间的转换

时间:2014-05-23 12:47:55

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

我们一般都知道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]
}

2 个答案:

答案 0 :(得分:0)

是的[conv.ptr]中有遗漏,适用的段落位于[expr.reinterpret.cast]

  

7可以将对象指针显式转换为对象指针   不同的类型。当一个prvalue v类型为&#34;指向T1&#34;是   转换为类型&#34;指向cv T2&#34;的指针,结果是   如果T1和T2都是static_cast<cv T2*>(static_cast<cv void*>(v))   标准布局类型(3.9)和T2的对齐要求是   没有比T1更严格,或者任何一种类型无效。转换一个   类型&#34的prvalue指向T1&#34;到类型&#34;指向T2&#34; (其中T1   和T2是对象类型,T2的对齐要求是   没有比T1更严格的并且回到原来的类型产生了   原始指针值。任何其他此类指针的结果   转换未指定。

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


编辑。评论中有一个问题是我在此编辑中更加明显,这不是语言律师问题,而是意图使用指针。我不确定关注是如何产生的,因为显而易见的是,人们可以在没有询问的情况下简单地进行C演员,但如果有疑问 - 指向int*的指针违反了strict aliasing规则。

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

答案 1 :(得分:0)

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

  

如果程序试图通过访问对象的存储值   行为是除以下类型之一以外的glvalue   未定义:

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

作为旁注,如果[ basic.lval ]不存在,则会出现其他问题:相同的大小并不代表相同的表示/范围。

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