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)。

数组对象及其第一个元素不是指针可相互转换的*,因此
重新解释的结果是一个类型为“指针指向数组的8
int
”的指针,其值为“指向[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
,这使得
流槽
未定义。@passery
int i;*reinterpret_cast(&i)=1;
尝试通过引用
i
float
类型的左值修改
i
int* p = a.data();