8

次の関数を (C99 で) 書きたいとします。

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

関数からそのような配列を返すにはどうすればよいですか? それは可能ですか?


0 (複合) と 1 (素数) で埋める配列を呼び出し元に割り当ててほしくないことに注意してください。n * sizeof(int)

呼び出し元は配列の長さを知る方法がないため、配列へのポインターを返すことはできません。

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 に答える