我能否反转数组到指针的衰变过程?

4
将指向数组第一个元素的指针强制转换为指向整个数组的指针是否合法?
template<typename T, size_t N>
void whatever(T(&)[N])
{
    std::cout << N << '\n';
}

int main()
{
    int a[10];
    int * p = a;
    whatever(*(int(*)[10])(p));   // <-- legal?
}

这段代码在我的编译器上输出的是10,但我不确定C++标准是否允许这样做。


2
好吧,如果我是你的话,我会打开标准并阅读。顺便说一句,我认为这是合法的。但我是Ruby开发人员,所以我知道什么呢? :-) - Sergio Tulentsev
我认为是这样的,因为您可以在指针中获取数组的地址并使用该指针访问元素零,然后您可以将该指针递增以访问数组其余的每个元素,或者将该指针用作数组本身。(i = p [5])但是我撤回了我的答案,并变成了一条评论,因为我的信仰无法与拥有32.7k声望的人(@Armen Tsirunyan)引用标准相抗衡。 - Mike Nakis
注意:模板在编译时解析,类型是您强制转换的类型,与“p”无关,即您可以从whatever( *(double(*)[10])0 )获得相同的输出,这与转换是否有意义完全无关。 - David Rodríguez - dribeas
2个回答

2
不,这是不合法的(即它是未定义行为)。整个数组的指针是&a而不是p。基本上,您正在将一个指针强制转换为另一个指针。标准描述了所有允许的转换,而这个转换不在其中。

那么我们可以将指向数组的指针视为指向第一个元素的指针,但是我们不能将指向第一个元素的指针视为指向数组的指针吗?或者这两个选项都不可行? - R. Martinho Fernandes
1
那么,int (*b)[10]; copy(&p, &p + sizeof(p), &b); 呢? - Kerrek SB
@R.MartinhoFernandes:两者都不是一个选项。 - Armen Tsirunyan
@KerrekSB:我不确定那个。 - Armen Tsirunyan
1
我认为这并不是未定义行为。那个转换是一个 reinterpret_cast,因此是未指定的(而不是未定义行为)。 - David Rodríguez - dribeas
@R.MartinhoFernandes: 你不能将一个指向数组的指针视为指向其第一个元素的指针。int ()[10]不能很顺利地转换为int - Xeo

0

我记得曾经得出结论:

  • 将指向POD结构体第一个元素的指针转换为指向整个POD结构体的指针
  • 将指向数组中一个元素的指针转换为指向大小足够小的数组的指针

这两种情况都是明确定义的。但如果第一个结论相当直接(即标准中有一节用非常简单的语言说明),那么第二个结论需要多个步骤(即需要将标准的几个部分组合起来并得出结论),而我现在没有时间重新搜索。如果没有人给出任何引用,我会尝试稍后回来。

编辑:我没有找到我的推理。目前我所拥有的只是,在假设reinterpret_cast产生与数组衰减相同的结果的情况下,“从数组指针到第一个元素指针再到数组指针”的往返是有保证的(根据C++98中的5.2.10/7),因为数组的对齐要求不能比元素的对齐要求更宽松。


所以你有一个证明,但它不适合这个边距?;-) - Kerrek SB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接