无法从’int *’转换为’int ‘?
我知道这可能是一个常见的问题,但我试图搜索但仍然找不到明确的答案。
我有以下代码:
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 []'
”
我发现这很奇怪,因为我已经读过指针和数组是相似的。 例如,我们可以使用[i]代替*(a + i)。 请问有人给我一个明确的解释吗?
这段代码实际上有两个错误。
首先,您返回临时的地址( f
的int数组),因此在函数返回后其内容未定义。 任何尝试访问返回指针指向的内存都将导致未定义的行为。
其次,在C ++中没有从指针到数组类型的隐式转换。 它们相似,但不完全相同。 数组可以衰减到指针,但它不会反过来因为信息在路上丢失 – 指针只代表一个内存地址,而数组代表连续区域的地址,通常具有特定的大小。 您也无法分配给数组。
例如,我们可以用[i]代替*(a + i)
然而,这与数组和指针之间的差异几乎没有关系,它只是指针类型的语法规则。 当数组衰减为指针时,它也适用于数组。
int[]
类型实际上并不存在。
定义和初始化数组时
int a[] = {1,2,3};
编译器对初始化程序中的元素进行计数,并创建一个正确大小的数组; 在那种情况下,它神奇地变成:
int a[3] = {1,2,3};
int[]
用作函数的参数,相反,它只是简单的int *
,即指向数组第一个元素的指针。 没有其他信息,特别是没有保留大小。 返回指针时也一样
请注意,数组不是指针:指针可以更改为指向其他内容,而数组总是指向同一个内存; 指针不知道它指向的内存空间有多大,而数组的大小在编译时总是知道的。 混淆源于这样一个事实:在许多情况下,数组衰减到指向其第一个元素的指针,并将它传递给函数/从函数返回它是这些情况中的一些。
那么,为什么你的代码不起作用? 有两个大错误:
-
您正在尝试使用指针初始化数组。 我们说
int *
没有任何关于数组大小的信息。 它只是指向第一个元素的指针。 所以编译器不知道应该做多大来容纳f()
返回的东西。 -
在
f
您将返回指向该函数本地变量的指针。 这是错误的,因为指针实际上并不存储数据,它只指向数据存储的位置,即在你的情况下指向f
a
本地。 因为该数组是函数的本地数组,所以当函数退出时(即return
),它就不再存在。这意味着您返回的指针指向不再存在的东西; 考虑代码:
int * a = f();
这个初始化工作,你可以尝试在函数中使用
a
晚,但是a
将指向不再存在的f
数组; 在最好的情况下,你的程序会崩溃(你会立即注意到你做错了什么),最糟糕的情况似乎会工作一段时间,然后开始给出奇怪的结果。
int *和int []相似但不同。 int *是一个实数指针,同时int []是一个数组引用(一种指向数据开头的“常量指针”),它不能被修改。 因此,int *可以像int []一样被威胁,但不能反之。
您可以互换地使用a[b]
和*(a+b)
因为当a
或b
中的一个是指针而另一个是整数或枚举类型时,这正是a[b]
的定义方式。
注意:这也意味着42[a]
类的表达式是完全合法的。 人类读者可能会强烈反对,但编译器不会盯着这一点。