C++ 将'a`T*`重新解释为'T(*)[N]`是一种未定义的行为吗?
考虑以下场景:C++ 将'a`T*`重新解释为'T(*)[N]`是一种未定义的行为吗?,c++,language-lawyer,reinterpret-cast,strict-aliasing,c++17,C++,Language Lawyer,Reinterpret Cast,Strict Aliasing,C++17,考虑以下场景: std::array<int, 8> a; auto p = reinterpret_cast<int(*)[8]>(a.data()); (*p)[0] = 42; std::数组a; 自动p=重新解释(a.数据()); (*p)[0]=42; 这是未定义的行为吗?我想是的 a.data() 关于CPP的参考资料似乎表明,reinterpret\u cast无效 作为一名程序员,我知道a.data()所指向的内存位置是一个8int对象数组 是否有
std::array<int, 8> a;
auto p = reinterpret_cast<int(*)[8]>(a.data());
(*p)[0] = 42;
std::数组a;
自动p=重新解释(a.数据());
(*p)[0]=42;
这是未定义的行为吗?我想是的
a.data()
- 关于CPP的参考资料似乎表明,
无效reinterpret\u cast
- 作为一名程序员,我知道
所指向的内存位置是一个a.data()
8
对象数组int
是否有我缺少的任何规则使此
重新解释\u cast
有效?是,行为未定义
int*
(a.data()
)的返回类型与int(*)[8]
)不同,因此您违反了严格的别名规则
当然(这更符合未来读者的利益)
是完全有效的,随后的表达式
p+n
也是如此,其中整数类型n
介于0和8之间(包括0和8)。数组对象及其第一个元素不是指针可相互转换的*,因此重新解释的结果是一个类型为“指针指向数组的8int
”的指针,其值为“指向[0]
”1的指针。换句话说,尽管类型不同,它实际上并不指向任何数组对象
然后,代码将数组到指针的转换应用到由取消引用此类指针而产生的左值(作为索引表达式(*p)[0]
的一部分)2.只有当左值实际引用数组对象时,才会指定该转换的行为3。由于本例中的左值没有,因此该行为未由omission4定义
*如果问题是“为什么数组对象及其第一个元素的指针不可相互转换?”,则已询问它: 1见,和 2见,和 3:“结果是指向数组的第一个元素的指针”
4:未定义的行为是“本文档未对其施加任何要求的行为”,包括“当本文档省略任何明确的行为定义时”。我正在铸造
.data()
虽然,但不是数组本身。@VittorioRomeo:Oops.更正了,答案仍然成立。在99.9999%的情况下,我认为这可能有用。我建议使用a来解决问题,而不是使用a。我认为这个答案仍然有误导性或输入错误:“int*
是与std::array*
完全不同的类型“-我不是在强制转换到std::array*
,而是转换到int(*)[8]
。@VittorioRomeo:再编辑一次-我倾向于此。std::array
必须是一个连续的容器。因此,问题归结为int*p
是否可以将[p;p+N)
已知为有效指针范围的int[N]
。误导性标题。进行指针强制转换从来都不是问题。潜在的问题是通过取消对强制转换结果的引用来访问内存。您是说std::array
不包含任何int[8]
子对象,或者你是说指针不指向该子对象?在这两种情况下,我认为这意味着a.data()+3
也是无效的,我们知道这应该是有效的。@hvd我是说指针指向int[8]的子对象
subobject;也就是说,它仍然指向数组的一个元素,而不是数组本身。只有在满足无额外可达性要求的情况下,才可以使用reinterpret\u cast
@hvd从指向元素的指针中获取指向数组的指针,这将取决于所涉及的数组。@hvd问题是您是否可以访问超出此范围的内容带有结果指针的子对象。例如,如果std::array
类似于struct{int E[8];char dummy;};
,则指向该int[8]的指针
是指针,可与指向整个结构的指针相互转换,因此可以到达dummy
,这使得流槽
未定义。@passeryint i;*reinterpret_cast(&i)=1;
尝试通过引用i
的float
类型的左值修改i
。
int* p = a.data();