8

假设我想(在 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 在编译时是未知的。


我在某处读到类似“用数组返回结构是一个可怕的想法”之类的东西,而且,嗯……那是我的最后一个想法。

在这种情况下,最佳做法是什么?

4

2 回答 2

11

如果您调用的函数必须决定它需要分配的实际元素数量,您应该将一个指向已分配长度的指针与其余参数一起传递,如下所示:

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;
}
于 2013-10-10T17:02:08.950 回答
4

当一个数组被分配时,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. 它将一个数组和它应该读取的元素数量(和元素的大小)作为参数。然后它返回它实际读取的元素数,如果到达文件末尾,则可能会更少。

于 2013-10-10T17:01:15.417 回答