我们一般都知道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]
}
答案 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)
long
和int
是两种不同的类型,即使它们的大小相同,我认为无效的转换是由于[ basic.lval.10 ]
如果程序试图通过访问对象的存储值 行为是除以下类型之一以外的glvalue 未定义:
- 对象的动态类型,
- 对象的动态类型的cv限定版本,
- 与对象的动态类型相似的类型(如4.4中所定义)
- 一种类型,是对应于动态类型的有符号或无符号类型 对象,
- 与对象的动态类型的cv限定版本对应的有符号或无符号类型的类型,
- 包含上述类型之一的聚合或联合类型 其元素或非静态数据成员(包括, 递归地,子聚合的子元素或非静态数据成员 包含联盟),
- 一种类型,它是对象动态类型的(可能是cv限定的)基类类型,
- char或unsigned char类型。
作为旁注,如果[ basic.lval ]不存在,则会出现其他问题:相同的大小并不代表相同的表示/范围。
无法保证int
中的值位与long
中的值位精确对应。