【问题标题】:Re allocating C array for more space重新分配 C 数组以获得更多空间
【发布时间】:2018-07-10 06:44:41
【问题描述】:

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

#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{
    }
}

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

【问题讨论】:

  • 先告诉我们您的问题。
  • 你从不使用realloc的返回值,而且似乎你想改变main::a,这种情况下你必须将a的地址传递给add
  • This realloc reference 应该会有所帮助。总结:调用realloc后,a可能不再有效。
  • 我意识到我一直在试验,忘记将我的代码恢复到之前的状态。那个 realloc 参考似乎是我正在寻找的,我会搞砸的。谢谢。

标签: c arrays pointers realloc


【解决方案1】:

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?

【讨论】:

  • 非常感谢您的帮助。你的权利,我引用的是副本而不是实际的指针。我会修复我的代码,ty ty
【解决方案2】:

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

辅助函数最好使用 2x 增长策略重新分配,因此您有一个 append 操作的摊销常数时间。

代码看起来有点像下面。

请注意,代码使用数组的前 2 个元素来保持其容量/大小。您可以改用指针 + 大小的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;
}

【讨论】:

  • push_back中设置vec是没有意义的,你需要参数是int** vec参数并用*vec = ...写入它。您也没有检查 realloc 是否失败
  • @dfogni - 你应该接受不同编码风格的存在。我更喜欢返回值表示法而不是输入/输出参数,因为我发现它更容易阅读。
  • @bobah 它与编码风格无关。提议的push_back 完全错误。调用者应该如何知道重新分配的数组在哪里?它如何知道重新分配是否失败?
猜你喜欢
  • 2020-02-29
  • 2011-05-03
  • 1970-01-01
  • 2016-05-24
  • 1970-01-01
  • 2018-03-20
  • 2012-06-17
  • 1970-01-01
  • 2021-08-27
相关资源
最近更新 更多