重新分配 C 数组以获得更多 space

Re allocating C array for more space

我正在编写一个带有函数 add(a , i, n) 的程序,它将 'i' 作为一个元素添加到 'a',但是如果数组 'a' 用完了space,那么我需要为数组重新分配更多内存。我被困在这里:

#include <stdlib.h>
#include <stdio.h>

int add(int* a, int i, int n);

int main(){
    int n = 20;
    int *a = (int*) malloc(n*sizeof(int));
    int i;

    for (i = 0; i < 100000; i++){
        n = add(a, i, n);
        printf("a[%d]=%d\n",i,(int)a[i]);
    }
    return 0;
}

int add(int *a, int i, int n){
    if (i >= n){
        n++;
        int* b = (int*) realloc(a, n*sizeof(int));
        a[i]=i;
        return n;
    }else{
    }
}

我不是很有经验,所以请温柔...

要在 C 中有一个自动增长的数组,您通常需要一个辅助函数 ensure_capacity 来处理数组重新分配。

辅助函数最好使用 2x 增长策略进行重新分配,这样您就有了 append 操作的摊销常数时间。

代码看起来有点像下面。

请注意,代码使用数组的前 2 个元素来保留其 capacity/size。您可以使用 struct 的指针 + 大小来代替,但是您需要使两者彼此靠近,否则代码将不容易阅读。

int* ensure_capacity(int* vec, int new_cap) {
    if (vec == 0) {
        vec = (int*) malloc(18 * sizeof(int));
        vec [0] = 16;
        vec [1] = 0;
    } else {
        int cap = vec[0];
        if (cap < new_cap) {
            do {
                cap *= 2;
            } while (cap < new_sz);
            int* new_vec = (int*) realloc(vec, cap * sizeof(int));
            if (new_vec != null) {
                vec = new_vec;
                vec[0] = cap;
            } else {
                // reallocation failed, handle the error
            }
        }
    }
    return vec;
}

您可以在 add() 函数中使用它,例如:

int* push_back(int* vec, int val) {
    vec = ensure_capacity(vec, vec[1] + 1);
    vec[vec[1]++] = val;
    return vec;
}

realloc 尝试重新分配给定的内存,但有时,它不能并给你一个新的内存指针。

必须像这样使用:

int *b;
b = realloc(a, <newsize>);
if (b) {
    /* realloc succeded, `a` must no longer be used */
    a = b;
    /* now a can be used */
    printf("ok\n");
} else {
    /* realloc failed, `a` is still available, but it's size did not changed */
    perror("realloc");
}

现在,您的代码仍有一些问题:

函数add()的思路是在需要的时候重新分配a,但是a是copy给的,所以在main中它的值不会改变.

#include <stdlib.h>
#include <stdio.h>

int add(int** a, int i, int n);

int main(){
    int n = 20;
    int *a = malloc(n*sizeof(int));
    int i;

    for (i = 0; i < 100000; i++) {
        /* note how `a` is passed to `add` */
        n = add(&a, i, n);
        printf("a[%d]=%d\n",i,a[i]);
    }
    /* and finally free `a`*/ 
    free(a);
    return 0;
}

/* changed `a` type to make its new value visible in `main` */
int add(int **a, int i, int n){
    if (i >= n){
        /* want to write a[i], so size must be at least i+1*/
        n = i+1;
        /* realloc memory */
        int *b = realloc(*a, n*sizeof(int));

        /* check that `realloc` succeded */
        if (!b) { 
            /* it failed!*/
            perror("realloc"); 
            exit(1);
        } 
        /* store new memory address */
        *a = b;
    }

    /* update memory */        
    (*a)[i]=i;        

    /* return new size */
    return n;
}

注意:我删除了 malloc/realloc 转换,请参阅:Do I cast the result of malloc?