为什么C不允许数组返回类型?

时间:2011-10-06 16:22:21

标签: c

为什么这在C

中有效
int * foo(int a,int b){
...
}

但这是无效的

int [] foo(int a,int b){
...
}

3 个答案:

答案 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;
}

ref

哪个看起来很简单,但内存retbuf会发生什么,指向函数末尾?调用函数可以信任它返回的指针中的数据吗?