2011-10-06 78 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點在函數結束?調用函數可以信任它返回的指針中的數據嗎?

相關問題