为什么这在C
中有效int * foo(int a,int b){
...
}
但这是无效的
int [] foo(int a,int b){
...
}
答案 0 :(得分:10)
语法有点滑稽。
int foo(int a, int b) []
{
...
}
但无论如何都不允许这样做。参见n1256 6.7.5.3第1段,“函数声明者”。
函数声明符不应指定函数类型或数组类型的返回类型。
您可以返回指向数组的指针:
int (*foo(int a, int b)) []; // Weird syntax, n'est-ce pas?
但你可能只是返回一个指针,因为以下是等价的:
int array[] = { ... };
int *x = array, (*y)[] = &array;
x[0];
(*y)[0]; // same as above, just with more cumbersome syntax
通常,如果函数需要返回int
数组,则返回指针或传入指针。其中一项:
int *func(int a, int b); // Allocated by func
void func(int a, int b, int *array); // Allocated by caller
void func(int a, int b, int **array); // Allocated by func
“struct-hack”也适用于具有固定大小的数组:
struct { int arr[50]; } array_struct;
struct array_struct func(int a, int b);
但除非数组很小,否则不建议这样做。
<强>理由:强>
数组通常很大,并且通常直到运行时才知道大小。由于参数和返回值是使用堆栈和寄存器传递的(在我知道的所有ABI上),并且堆栈具有固定的大小,因此在堆栈上传递这样大的对象有点危险。某些ABI也不能正常处理大的返回值,可能会导致生成额外的返回值副本。
以下代码也可能存在危险:
void func(...)
{
int arr[BIG_NUMBER]; // potential for stack overflow
int *ptr = alloca(sizeof(int) * BIG_NUMBER); // potential for stack overflow
}
答案 1 :(得分:4)
在C中传递数组的值不是直接支持的(即使你写int []
作为参数实际上被解释为int *
),如果我没记错的话,它是某种神器BCPL到C。
话虽这么说,你实际上可以将封装它们的数组返回到struct
s:
struct
{
int value[20]
} foo(int a, int b)
{
/* ... */
}
(这个技巧显然也适用于参数)
答案 2 :(得分:0)
首先,回想一下C中的数组实际上只是指向内存块指针的语法糖。所以C并没有通过强制使用前一种表示法来限制语言的功能(参见下面的例子)。
此外,他们可能已做出这样的选择,以防止早期程序员编写如下代码:
char *itoa(int n){
char retbuf[25];
sprintf(retbuf, "%d", n);
return retbuf;
}
哪个看起来很简单,但内存retbuf
会发生什么,指向函数末尾?调用函数可以信任它返回的指针中的数据吗?