2011-10-06 75 views
1

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

int * foo(int a,int b){ 
... 
} 

这个有效的,但这是无效

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

相关(被问到关于C++,但接受的答案谈论关于C,因为它是基础):http://stackoverflow.com/questions/5157439/why-doesnt-c-support-functions-returning-arrays – birryree

回答

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 { 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 
} 
+0

@ abelenky:搜索“C声明符语法”。您也可以浏览C标准的草稿,就标准尺寸而言,这些草稿的可读性是相当可读的。 –

+0

为什么在函数不允许返回数组时声明一个返回数组的函数的语法? – Caleb

+0

@Caleb:有很多东西没有意义,但有语法,比如'x =&func();'。通常通过编译器检查语言的词法,语法和类型正确性。给定的错误是“语法错误”还是“类型错误”是一个选择问题。通常,修改语法将某些东西变成语法错误会使语法*变得更加复杂,甚至会迫使编译器编写者使用完全不同的解析算法。所以,容易做的事情就是将其改为类型错误。与例如Lisp,语法错误不会发生。 –

4

在由C值传递数组不直接支持(甚至当你写int []作为参数实际上是解释为int *),如果我没记错的话这是某种通道的神器从BCPL到C.

话虽这么说,你其实可以返回数组封装他们到struct S:

struct 
{ 
    int value[20] 
} foo(int a, int b) 
{ 
    /* ... */ 
} 

(这个技巧显然也适用于参数)

0

首先,回想一下C中的数组实际上只是指向内存块的语法糖。所以C不会通过强制使用前面的符号来限制该语言的功能(参见下面的例子)。

而且,他们可能已经做出了这个选择,以防止早期程序员从写这样的代码:

char *itoa(int n){ 
    char retbuf[25]; 
    sprintf(retbuf, "%d", n); 
    return retbuf; 
} 

ref

它看起来很简单,但会发生什么变化内存retbuf点在函数结束?调用函数可以信任它返回的指针中的数据吗?

相关问题