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