2013-10-10 65 views
2

假設我想寫(在C99)以下功能:Ç - 未知大小的數組回報

NAME: primes 
INPUT: an integer n > 0 
OUTPUT: int array filled with the prime numbers in range [2, n] 

如何從我的函數返回這樣的一個數組?那可能嗎?


注意,我所需號碼分配的n * sizeof(int)陣列,我會用0(複合)和1(質數)填寫。

我不能只返回一個指向數組,因爲主叫方沒有辦法知道數組有多長:

int * primes(int n) 
{ 
    int * arr = malloc(n * sizeof(int)); 
    // do stuff 
    return arr; 
} 

int main(void) 
{ 
    int * arr = primes(100); 
    printf("%lu \n", sizeof arr); // prints 8 
} 

,我不能更改簽名是這樣的:

int (*primes(int n))[LENGTH] 

因爲在編譯時LENGTH是未知的。


我讀的地方有點像「與陣列返回一個結構是一個可怕的想法」,並且,嗯......那是我最後的想法。

這種情況下的最佳做法是什麼?

+0

你可以返回一個分配的指針,因爲你顯示,這不是一個問題。但是,'sizeof(arr)'將是指針的大小,而不是數組的長度。所以你會得到8你在一臺64位機器上。 – lurker

+0

@mbratch這就是問題所在。如果調用者想要迭代素數會怎麼樣? 'for(int i = 0; i Haile

+0

顯示一些代碼,您希望迭代如何工作。您需要以某種方式定義'??????'。用戶如何決定這個數字? – lurker

回答

5

如果你打電話必須決定要素的實際數量,它需要分配的功能,你應該通過一個指針分配的長度與參數的其餘一起,就像這樣:

size_t actual_length; 
int *arr = primes(100, &actual_length); 
if (arr == NULL) { 
    ... // Report an error 
} 
for (size_t i = 0 ; i != actual_length ; i++) { 
    printf("%d\n", array[i]); 
} 

primes然後看起來像這樣:

int *primes(int count, size_t *actual_length) { 
    size_t primes_needed = ... 
    int *res = malloc(sizeof(*res)*primes_needed); 
    *actual_length = primes_needed; 
    // Do calculations, perhaps some reallocs 
    // Don't forget to reassign *actual_length = ... on realloc 
    ... 
    return res; 
} 
+0

這完全是**我正在尋找的那種成語。 – Haile

+0

+1幾乎完美,但可能將'sizeof(int)'更改爲'sizeof * res' :) – 2013-10-10 17:18:45

+0

@ H2CO3這是一個很好的變化,很有意義。謝謝! – dasblinkenlight

2

當數組與malloc分配時,您無法通過sizeof請求其大小。在這些情況下的常見做法是返回數組的大小並將其分配給作爲參數給出的指針指針。就像這樣:

int primes(int n, int ** arr){ 
    int length = n; 
    *arr = malloc(length * sizeof(int)); 
    // do stuff... 
    // if *arr is realloc()ed update length 
    return length; 
} 

,然後調用它像這樣:

int * arr; 
length = primes(100, &arr); 

,這是否是fread一個標準功能的一個例子。它需要將一個數組和元素的數量(以及元素的大小)作爲參數。然後它返回它實際讀取的元素的數量,如果例如文件的末尾已經達到,這可能會更少。

+0

我對你的例子有點困惑(或者我無法理解它)。你返回'n',但'n'不是素數組的大小。該數組只包含範圍[2,n]中的素數,其長度小於n。 – Haile

+0

啊,是的,我正在使用原始'primes'函數,它使用'n'作爲最初的'malloc'。如果數組大小發生變化,您可以在函數中更改'n'。 – Kninnug

+0

「如果在編譯時不知道數組的大小,你不能使用sizeof來請求它」 - 錯誤的,我們自1999年以來有了VLA。「sizeof與宏相比更類似於函數」 - 錯誤,它不是一個宏,它是一個**運算符。** – 2013-10-10 17:19:28