更改二维动态数组(c中的realloc)

时间:2017-10-09 07:27:00

标签: c arrays malloc realloc

我有一个动态的二维数组,大小是高度*宽度。

我想使用realloc更改数组大小。

这是我的代码,但它无效。

我该怎么办?帮帮我!!

int main(){
      char **img;
      img = (char**)malloc(sizeof(char*)*height);

      for(i=0;i<height;i++){
        img[i] = (char*) malloc(sizeof(char)*width);
      }

      resize(height*2, width*2, img);
}

void resize(int height, int width, char **img){
      int i;
      img = (char**)realloc(img, sizeof(char)*height);
      for(i=0;i<h;i++){
         img[i] = (char*)realloc(img[i], width);
      }

}

3 个答案:

答案 0 :(得分:0)

除了你

  • 没有处理2D数组和
  • 如果新高度小于旧高度,则
  • 和代码泄漏内存
  • 您无需在C和
  • 中投射void - 指针
  • 所有int应为size_t s

这里有两个主要的错误,如代码

  • 传递错误的大小以重新分配外部数组。它将height乘以sizeof (char)而不是sizeof (char*)
  • 错过初始化&#34;外部&#34;的其他指针realloc。带有NULL的数组,然后通过内部调整大小循环将它们传递给realloc()

因此,假设新高度大于或等于旧高度的最小调整可能看起来像

void resize(size_t height, size_t height_current, size_t width, char **img){
  int i;
  img = (char**)realloc(img, sizeof(char*)*height);
  for(i=height_current;i<height;i++){
     img[i] = NULL;
  }
  for(i=0;i<width;i++){ // correct copypasta mistake here
     img[i] = (char*)realloc(img[i], width); 
  }
}

更好的版本可能看起来像这样

void resize(size_t height, size_t height_current, size_t width, size_t char **img)
{
  if (height != height_current)
  {
    if (height < height_current)
    {
      for (size_t i = height; i < height_current; ++i)
      {
         free(img[i]);
      }
    }

    img = realloc(img, height * sizeof *img);

    if (height > height_current)
    {
      for (size_t i = height_current; i < height; ++i)
      {
         img[i] = NULL;
      }
    }
  }

  for (size_t i = 0; i < width; ++i)
  {
     img[i] = realloc(img[i], width * sizeof *img[i]);
  }
}

这样称呼:

resize(height*2, height, width*2, img);

此外,您确实想要对所有对malloc()realloc()的调用添加错误检查,因为它们可能会失败!

答案 1 :(得分:0)

有两个主要问题。首先,realloc可以将内存块移动到新位置。因此realloc的返回值指向&#34; old&#34;如果不需要移动,则为内存块;如果需要移动,则为新块;如果发生错误,则为NULL。然而你忽略了resize中的这个事实,因为它无法改变调用者传入的指针对象。我建议调整原型使resize返回一个(可能是新的)指针就像realloc确实如此。

其次,在重新分配每一行时,数组中可能存在未初始化的值,可能指向&#34;某处&#34;。重新分配这样一个未初始化的值是未定义的行为。我建议设置&#34; new&#34;行NULL使得realloc之后可以正常行为。因此有必要知道&#34; old&#34;高度,因为你没有机会区分定期初始化的指针和&#34;垃圾&#34;指针。

参见改编的代码。希望它有所帮助。

char** resize(int oldHeight, int oldWidth, int height, int width, char **img){
    int i;
    img = realloc(img, sizeof(char)*height);
    for (int i=oldHeight; i<height; i++)
        img[i] = NULL;

    for(i=0;i<height;i++){
        img[i] = realloc(img[i], width);
        for (int col=oldWidth; col < width; col++) {
            img[i][col] = 0;
        }
    }

    return img;
}

int main(){
    int height = 10;
    int width = 20;

    char **img;
    img = malloc(sizeof(char*)*height);

    for(int i=0;i<height;i++){
        img[i] = malloc(sizeof(char)*width);
    }

    img = resize(height, width, height*2, width*2, img);
}

答案 2 :(得分:0)

要正确执行此操作,必须在调整大小之前至少知道行数。一种可能性是定义包含附加信息的struct(一种OOP方法,将所有相关数据放在一起),如下例所示(也存储列数,仅用于完整性,未经测试的代码):

#include <stdlib.h>
#include <string.h>

typedef struct Lookup Lookup;

struct Lookup
{
    size_t rows;
    size_t cols;
    char **data;
};

static void Lookup_destroy(Lookup *self)
{
    if (!self) return;
    for (size_t r = 0; r < self->rows; ++r)
    {
        free(self->data[r]);
    }
    free(self->data);
    free(self);
}

static Lookup *Lookup_create(size_t rows, size_t cols)
{
    Lookup *self = malloc(sizeof *self);
    if (!self) return 0;

    self->rows = rows;
    self->cols = cols;
    self->data = malloc(rows * sizeof *(self->data));
    if (!self->data)
    {
        free(self);
        return 0;
    }
    memset(self->data, 0, rows * sizeof *(self->data));
    for (size_t r = 0; r < rows; ++r)
    {
        self->data[r] = malloc(cols * sizeof *(self->data[r]));
        if (!self->data[r])
        {
            Lookup_destroy(self);
            return 0;
        }
    }

    return self;
}

static Lookup *Lookup_resize(Lookup *self, size_t rows, size_t cols)
{
    if (!self) return Lookup_create(rows, cols);

    // free rows that are no longer needed, if any:
    for (size_t r = rows; r < self->rows; ++r)
    {
        free(self->data[r]);
        self->data[r] = 0;
    }

    // reallocate array of rows:
    char **newdata = realloc(self->data, rows * sizeof *newdata);
    if (!newdata)
    {
        Lookup_destroy(self);
        return 0;
    }

    // update row array and row count: 
    self->data = newdata;
    size_t oldrows = self->rows;
    self->rows = rows;

    // initialize new rows to NULL, if any:
    if (rows > oldrows)
    {
        memset(self->data + oldrows, 0,
                (rows - oldrows) * sizeof *(self->data));
    }

    // reallocate individual rows:
    for (size_t r = 0; r < rows; ++r)
    {
        char *newrow = realloc(self->data[r], cols * sizeof *newrow);
        if (!newrow)
        {
            Lookup_destroy(self);
            return 0;
        }
        self->data[r] = newrow;
    }

    // update col count:
    self->cols = cols;

    return self;
}

请注意realloc()的结果总是首先存储到临时变量,这是正确处理错误所必需的。如果出现任何错误,此代码会丢弃整个对象 - 当然,您可以使用更多代码执行不同的操作。

您可以在代码中使用它:

int main(){
      Lookup img;
      img = Lookup_create(height, width);
      // check for NULL here

      img = Lookup_resize(img, height*2, width*2);
      // and check for NULL here
}