无法从"int *"转换为"int []"?

Cannot convert from 'int *' to 'int []'?

本文关键字:int 转换      更新时间:2023-10-16

我知道这可能是一个常见的问题,但我已经尝试过搜索,但仍然找不到明确的答案。

我有以下代码:

int* f() {
    int a[] = {1,2,3};
    return a;
}
int main() {
    int a[] = f(); // Error here
    getch();
    return 0;
}

此代码产生错误消息:"Cannot convert from 'int *' to 'int []'"

我发现这很奇怪,因为我读到指针和数组是相似的。例如,我们可以使用a[i]代替*(a+i)。谁能给我一个清楚的解释吗?

这段代码中实际上有两个错误。

首先,您要返回一个临时(f中的int数组)的地址,因此在函数返回后,其内容是未定义的。任何访问返回指针指向的内存的尝试都将导致未定义的行为。

其次,C++中没有从指针到数组类型的隐式转换。它们相似,但并不完全相同。数组可以衰减为指针,但由于信息在途中丢失,它不会反过来工作——指针只代表内存地址,而数组代表连续区域的地址,通常具有特定的大小。此外,您不能分配给数组。

例如,我们可以使用[i]而不是*(a+i)

然而,这与数组和指针之间的差异无关,这只是指针类型的语法规则。当数组衰减为指针时,它也适用于数组。

类型int[]实际上并不存在。

当您定义并初始化像这样的阵列时

int a[] = {1,2,3};

编译器对初始化器中的元素进行计数,并创建一个大小合适的数组;在这种情况下,它神奇地变成:

int a[3] = {1,2,3};

int[]用作函数的参数,相反,它只是普通的int *,即指向数组第一个元素的指针。它没有携带其他信息,特别是没有保存任何关于大小的信息。返回指针时也是如此

请注意,数组不是指针:指针可以更改为指向其他内容,而数组总是指向同一内存;指针不知道它所指向的内存空间有多大,而数组的大小在编译时总是已知的。在许多情况下,数组会衰减到指向其第一个元素的指针,而将其传递给函数/从函数返回就是其中的一些情况。

那么,为什么你的代码不起作用呢?有两个大错误:

  1. 您正试图用指针初始化数组。我们说过int *不携带任何关于数组大小的信息。它只是指向第一个元素的指针。因此编译器不知道a应该有多大才能容纳f()返回的内容。

  2. f中,您将返回一个指向该函数本地变量的指针。这是错误的,因为指针实际上并不存储数据,它只指向存储数据的位置,即在您的情况下指向f本地的a。因为该数组是函数的局部,所以当函数退出时(即在return),它就不存在了。

    这意味着你正在返回的指针指向已经不存在的东西;考虑代码:

    int * a = f();
    

    此初始化有效,您可以稍后在函数中尝试使用a,但a将指向不再存在的f数组;在最好的情况下,你的程序会崩溃(你会立即注意到你做错了什么),在最坏的情况下它似乎会工作一段时间,然后开始给出奇怪的结果。

int*和int[]相似但不同。int*是一个实指针,而int[]是一个不能修改的数组引用(一种指向数据开头的"常量指针")。因此,int*可以像int[]一样被威胁,但不能被威胁。

您可以互换使用a[b]*(a+b),因为当ab中的一个是指针,而另一个是整数或枚举类型时,a[b]就是这样定义的。

注意:这也意味着像42[a]这样的表达式是完全合法的。人类读者可能会强烈反对,但编译器不会对此视而不见。