【问题标题】:how to realloc an empty 2d array如何重新分配一个空的二维数组
【发布时间】:2018-02-27 17:12:07
【问题描述】:

我有一个被多次调用的函数,其参数n 定义了n*2 大小的二维数组:

void myfunc(int n){

  static int n0=0,i;
  static double **x=NULL;

  if(n>n0){ //realloc if n grows
    x=(double **)realloc(x,n*sizeof(double*)));
    for(i=0;i<n;i++){
      x[i]=(double *)realloc(x[i],2*sizeof(double))); // <--problem here
    }
    n0=n;
  }

}

在第一次调用时,**x 被初始化为 NULL,但 x[i] 不是,因此第二个 realloc 的行为可能不正确。

有没有办法在不首先使用malloccalloc 的情况下realloc 空二维矩阵的行?

【问题讨论】:

  • 指向指针的指针不是二维数组。
  • 在 C++ 中?不是这样的!请选择一种语言,C和C++是两种非常不同的语言,没有理智的C++程序员会做这样的事情。
  • 至于你的问题,你确实知道函数是否第一次被调用。想想你将x 初始化为...
  • 不同之处在于二维数组是一个具有固定维度的连续内存区域。在您的情况下,它指向不同的区域,并且每个“行”可能有不同数量的“列”。
  • 在这种情况下,没有。 realloc 只重新分配内存,它不会初始化内存中未初始化的部分。

标签: c arrays malloc realloc


【解决方案1】:

在这里,您应该使用malloc() 而不是realloc(),因为您没有重新在这里分配内存。

但如果您的代码无法知道数据是否是新的,则应首先将其初始化为 NULL 以便 realloc() 工作。

【讨论】:

  • 如果myfunc 被多次调用,n 的值不同,那么 IMO 没问题。好吧,如果它没有充满其他问题的话。
  • 我不能使用malloc,因为连续调用会造成内存泄漏。我需要realloc,不知道数据是不是新的。
  • @dude: 如果你说有问题请列举出来
【解决方案2】:

我会更改函数,第一次使用malloc,之后使用realloc

但是,对于x 的当前元素,不需要reallocx的新元素只需要使用malloc即可。

void myfunc(int n)
{
   static int n0 = 0;
   static double **x = NULL;

   if ( n > n0)
   {
      if ( x == NULL )
      {
         // Use malloc to get memory for x
         x = malloc(n*sizeof(double*));

         for( int i = 0; i < n; i++)
         {
            x[i] = malloc(2*sizeof(double));
         }
      }
      else
      {
         // Use realloc to get more memory for x.
         x = realloc(x, n*sizeof(double*));

         // Allocate memory only for the new elements of x.
         for( int i = n0; i < n; i++)
         {
            x[i] = malloc(2*sizeof(double));
         }
      }

      n0 = n;
   }
}

PS 不要强制转换mallocrealloc 的返回值。请参阅Specifically, what's dangerous about casting the result of malloc? 了解原因。


经过一番思考,我意识到功能可以简化一点。

void myfunc(int n)
{
   static int n0 = 0;
   static double **x = NULL;

   if ( n > n0)
   {
      if ( x == NULL )
      {
         // Use malloc
         x = malloc(n*sizeof(double*));
      }
      else
      {
         // Use realloc
         x = realloc(x, n*sizeof(double*));
      }

      // Use malloc for the new elements of x.
      // When n0 is 0, it will be all of them.
      for( int i = n0; i < n; i++)
      {
         x[i] = malloc(2*sizeof(double));
      }

      n0 = n;
   }
}

【讨论】:

  • 感谢您提供有关选角的提示。关于解决方案,那么在第二个 realloc 之前添加一行可能会更容易:if(n0==0) x[i]=NULL;
  • @cipper,你希望从中获得什么?
  • @cipper,请参阅更新后的答案。您可以决定是否需要使用x[i] = NULL;
  • @R Sahu:是的,通过将循环限制为n0..n 它也可以解决。好主意,谢谢!
  • @R Sahu:但再想想,realloc 之后 x[0]..x[n0] 是否保持不变?他们不需要重新分配吗?
【解决方案3】:
void myfunc(int n){

  static int n0=0,i;
  static double **x=NULL;

  if(n>n0){
    x=realloc(x,n*sizeof(double*)));
    for(i=n0;i<n;i++){
      x[i]=malloc(2*sizeof(double)));
    }
    n0=n;
  }

}

【讨论】:

    【解决方案4】:

    除了详细说明如何增加分配的各种答案外,还可以更改代码以通过调用myfunc(0) 最终释放分配。

    最好使用size_t 来调整数组大小。

    i 不需要是static

    这个函数隐藏了它的结果,也许是返回指针?

    double **myfunc(size_t n) {
      static size_t n0 = 0;
      static double **x = NULL;
    
      if (n > n0) {
        void *new_ptr = realloc(x, sizeof *x * n);
        if (new_ptr == NULL) {
          TBD_Code();  // Handle out-of-memory
        }
        x = new_ptr;
        for (size_t i = n0; i < n; i++) {
          x[i] = malloc(sizeof *(x[i]) * 2);
        }
        n0 = n;
      } else if (n == 0) {
        while (n0 > 0) [
          free(x[--n0]);
        }
        free(x);
        x = NULL;
      }
      return x;
    }
    

    考虑ptr = malloc(sizeof *ptr * n); 使用*alloc() 的风格。比ptr = malloc(sizeof (de-referenced_ptr_type) * n);更容易正确编码、审查和维护

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 2021-10-11
      • 1970-01-01
      • 2012-03-27
      相关资源
      最近更新 更多