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



为什么这在C中有效

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

但这是无效的

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

语法有点奇怪。

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
}

在C中,不直接支持按值传递数组(即使您将int []作为参数实际上解释为int *),如果我没记错的话,这是从BCPL到C的通道的某种工件。

话虽如此,您实际上可以返回将它们封装到struct s中的数组:

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

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

首先,回想一下C中的数组实际上只是指向内存块指针的语法糖。因此,C并没有通过强制使用前一种符号来限制该语言的功能(参见下面的示例)。

同样,他们这样做可能是为了防止早期的程序员编写这样的代码:

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

ref

这看起来很简单,但是在函数结束时retbuf指向的内存发生了什么?调用函数是否可以信任指针中的数据?

最新更新