Tutorial :How do I dynamically allocate a 2D array of structs?



Question:

The dimensions are unknown at compile time, so I'm trying to allocate a 2D array of structs dynamically. The code compiles but I get a bad access when accessing an element.

// The struct  typedef struct  {      NSInteger numActors;      Actor *a1;      Actor *a2;      Actor *a3;      Actor *a4;      Actor *a5;  } GridNode;    // In interface  GridNode **grid;    // In init  NSInteger nx = inFrame.size.width / blockSize;  NSInteger ny = inFrame.size.height / blockSize;  grid = malloc(sizeof(GridNode) * nx * ny);  grid[10][20].numActors = 3; // EXC_BAD_ACCESS  


Solution:1

Roughly the code should look like:

grid = (GridNode **) malloc(sizeof(GridNode *) * nx);  int i;  for(i = 0; i < nx; i++) {      grid[i] = (GridNode *) malloc(sizeof(GridNode) * ny);  }  

And remember to free them.


Solution:2

C has only 1D arrays, so 2D ones can be defined in two ways:

  1. As an array of arrays, like GridNode **grid, so to be accessed by grid[x][y], but then you have to init each row separately (right, as yehnan managed to anwser first):

    grid=malloc(sizeof(GridNode*)*nx);    for(int e=0;e<nx;e++) grid[e]=malloc(sizeof(GridNode)*ny);  
  2. As a 1D array with tricky indexing:

    grid=malloc(sizeof(GridNode)*nx*ny);    grid[(10-1)*nx+20] //grid[10,20]  


Solution:3

A simpler alternative would be to create a single-dimension NSArray or NSMutableArray and use a little math to access the correct row and column:

NSUInteger width  = 10;  NSUInteger height = 10;  NSUInteger size   = width * height;  NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:size];  

To insert a GridNode at row 5, column 3, you could do this:

NSUInteger index = (row - 1) * width + col;  [array insertObject:myNode atIndex:index];  

To retrieve a node from row 2 column 6 you would do:

NSUInteger index = (row - 1) * width + col;  [array objectAtIndex:index];  

The memory in your computer is of a single dimension. The multi-dimensional addressing that we're all familiar with from C is really just syntactic sugar that performs a similar operation as I've shown above.

The only caveat I can think of is that you will probably have to convert GridNode from a C structure to an Objective-C class for this to work.


Solution:4

The concept behind your allocation is wrong.

Assuming x is your second dimension ([20] in your example) and y is your first dimension ([10] in your example), the y elements are just pointers to arrays of x. So conceptually, you would do

D'oh', yehnan beat me to it.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »