将结构数组指针作为函数参数传递?

时间:2014-05-13 14:35:44

标签: c arrays function arguments

如果我直接使用struct数组的名称进行分配,而不是函数参数,则代码可以工作。否则会返回内存错误。

typedef struct COORD
{
  int xp;
  int yp;
} coord;

coord** xy;

void allocate(coord** COORD)
{
  int i;

  //allocate COORD[500][460]
  COORD = (coord**)malloc(sizeof(coord*)*500);
  for(i=0; i<500; i++)
  {
    COORD[i] = (coord*)malloc(sizeof(coord)*460);
  }

  // freeing
  for (i=0; i<500; i++) free(COORD[i]);
  free(COORD);
}
//function call: allocate(xy);
//That is the code that leeds to the error

仅使用xy代替COORD。我不知道为什么这不起作用。

5 个答案:

答案 0 :(得分:3)

您正在混合各种编码样式。目前尚不清楚您想要实现的目标。根据你的任务选择一个。

临时缓冲区

您需要一个应在堆上分配的大型临时缓冲区,而不需要从外部查看。只需创建一个局部变量:

void do_stuff(int w, int h)
{
    coord **p;
    int i;

    p = malloc(h * sizeof(*p));
    for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));;

    // do stuff

    for (i = 0; i < h; i++) free(p[i]);
    free(p);
}

分配内存以供进一步使用

您希望分配客户端代码可以使用的存储空间。然后提供两个函数,一个分配,另一个释放内存:

coord **create(int w, int h)
{
    coord **p;
    int i;

    p = malloc(h * sizeof(*p));
    for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));

    return p;
}

void destroy(coord **p, int h)
{
    int i;

    for (i = 0; i < h; i++) free(p[i]);
    free(p);
}

您的客户端代码可以在这些调用之间使用内存:

coord **p = create(500, 460);

// do stuff

drestroy(p, 500);

(请注意,您必须将高度传递给destroy,这有点不幸。创建一个包含宽度和高度以及指针信息的包装器结构可能更清晰。)

为全局变量

分配内存

您有一个全局指针实例。然后你的功能总是在指针上运行,你不需要任何进一步的信息(尺寸除外):

coord **global = NULL;

void destroy_global(int h)
{
    int i;

    for (i = 0; i < h; i++) free(global[i]);
    free(global);
    global = NULL;
}  

void create_global(int w, int h)
{
    int i;

    if (global != NULL) free_global();

    global = alloc(h * sizeof(*global));
    for (i = 0; i < h; i++) global[i] = malloc(w * sizeof(**global));        
}

请注意,您应该为所有内存函数和<stdlib.h>宏添加NULL

附录根据您的评论,您希望为位图分配内存。上面的选项2。

我建议创建一个对象结构。你可以将一个指针v作为句柄传递给一堆函数。您可以使用返回该句柄的函数创建对象。

下面简要介绍了位图对象的粗略设计。

typedef struct Pixel Pixel;
typedef struct Bitmap Bitmap;

struct Pixel {
    uint8_t r, g, b;
};

struct Bitmap {
    int height;
    int width;
    Pixel **pixel;
};

Bitmap *bitmap_new(int w, int h)
{
    Bitmap *bmp = malloc(sizeof(*bmp));
    int i;

    bmp->height = h;
    bmp->width = w;
    bmp->pixel = malloc(h * sizeof(*bmp->pixel));
    for (i = 0; i < h; i++) {
        bmp->pixel[i] = malloc(w * sizeof(**bmp->pixel));
    }

    return p;
}

void bitmap_delete(Bitmap *bmp)
{
    int i;

    for (i = 0; i < h; i++) free(bmp->pixel[i]);
    free(bmp->pixel);
    free(bmp);
}



Bitmap *bitmap_read(const char *fn)
{
    Bitmap *bmp;
    FILE *f = fopen(fn, "rb");

    // read and allocate 
    return bmp;
}

void bitmap_blank(Bitmap *bmp, int r, int g, int b)
{
    for (i = 0; i < bitmap->height; i++) {
        for (j = 0; j < bitmap->width; j++) {
            bmp->pixel[i][j].r = r;
            bmp->pixel[i][j].g = g;
            bmp->pixel[i][j].b = b;
        }
    }
}

void bitmap_mirror_x(Bitmap *bmp)
{
    // do stuff
}

int bitmap_write(Bitmap *bmp, const char *fn)
{
    FILE *f = fopen(fn, "rb");

    // write bitmap to file
    return 0;
}

该设计类似于FILE *的界面:fopen为您提供句柄(或NULL;上面的代码中省略了错误检查)和freadfprintffseek和family将指向文件的指针作为参数。最后调用fclose关闭磁盘上的文件并释放fopen声明的任何资源。

答案 1 :(得分:0)

问题是函数allocate()无法在其外部更改xy的值。这是因为C是call by value,被调用函数只获取其参数的值,而不是对调用者上下文中表达式的任何类型的引用。

需要:

void allocate(coord ***c)
{
}

coord **xy;
allocate(&xy);

当然是愚蠢的:正确的设计是allocate() 返回新地址:

coord ** allocate(void)
{
}

使用如下:

coord **xy = allocate();

将尺寸作为函数的参数可能会更好,因为幻数通常不是一件好事:

coord ** allocate(size_t width, size_t height);

答案 2 :(得分:0)

您是否尝试过编译此代码?有很多错误。

首先,main的类型总是是'int main(int argc,char * argv [])' 其次,你需要'#include&lt; stdlib.h&gt;'在你的文件的顶部,以获得malloc / free和朋友的返回类型。 第三,你没有宣称'我'。 第四,您使用相同名称“COORD”作为结构名称和变量。不要这样做,它会给你带来麻烦。

发送错误的代码使得很难弄清楚问题的根源是什么,但我怀疑这是“COORD”的超载。

答案 3 :(得分:0)

typedef struct COORD
{
  int xp;
  int yp;
} coord;

coord** xy;

void allocate(coord** COORD)
{
  int i;

  //allocate COORD[500][460]
  COORD = (coord**)malloc(sizeof(coord*)*500);
  for(i=0; i<500; i++)
  {
    COORD[i] = (coord*)malloc(sizeof(coord)*460);
  }

  // freeing
  for (i=0; i<500; i++) free(COORD[i]);
  free(COORD);
}
//function call: allocate();
//That is the code that works

答案 4 :(得分:0)

typedef struct
{
  int xp;
  int yp;
} Coord;

Coord **xy;

Coord** allocate(size_t height, size_t width)
{
  int i;
  Coord **arr;

  arr = malloc(sizeof(Coord*)*height);
  for(i=0; i<height; i++) {
    arr[i] = malloc(sizeof(coord)*width);
  }
  return arr;
}

void allocate2(Coord ***p_arr, size_t height, size_t width)
{
  int i;
  Coord **arr;

  arr = *p_arr;

  arr = malloc(sizeof(Coord*)*height);
  for(i=0; i<height; i++) {
    arr[i] = malloc(sizeof(coord)*width);
  }
}

void deallocate(Coord **arr, size_t height)
{
  for (i=0; i<500; i++) {
    free(arr[i]);
  }
  free(arr);
}

int main()
{
  Coord **arr_2;
  Coord ***p_arr_3;

  allocate2(&xy, 500, 460);
  /* do something with global array, xy, e.g. */
  xy[1][2].xp = 100;
  xy[1][2].yp = 200;
  deallocate(xy, 500);

  arr_2 = allocate(500, 460);
  /* do something with local array, arr_2 */
  deallocate(arr_2, 500);

  allocate2(p_arr_3, 500, 460);
  /* do something with ptr to local array, p_arr_3 */
  deallocate(*p_arr_3, 500);

  return 0;
}