CheapGucciClothing
CheapGucciClothing

Reputation: 73

Fill a 2d array of pointers with pointers to structs in C

I have a 2 dimensional array of pointers:

typedef struct Cell{
   Position p;
   unsigned int value;
} Cell;

typedef struct Position{
    unsigned int x;
    unsigned int y;
} Position;

int size = 4;
Cell ***cells = malloc(sizeof(Cell**) * size);
int i,j;
for(i = 0; i < size; i++){
    cells[i] = malloc(sizeof(Cell*) * size);
    for(j = 0; j < size; j++){
        cells[i][j] = malloc(sizeof(Cell));
    }
}

What I want to do now is fill this array with pointers to cells, and initialize these cells to contain the value 0 like this:

for(i = 0; i < size; i++){
    for(j = 0; j < size; j++){
        Position p = {i,j};
        Cell c = {p, 0};
        cells[i][j] = &c; //This doesn't work
    }
}

As you can already tell, writing the address of c into the pointer cells[i][j] is less than ideal, since every pointer now points to the same address. However I don't know how to fill this array with pointers pointing to individual addresses.

I tried something like this:

cells[i][j]->value = 0;

which of course also doesn't work. Can anyone give me a hint on how I can solve my problem?

Upvotes: 2

Views: 128

Answers (3)

Ted Lyngmo
Ted Lyngmo

Reputation: 117228

You've already gotten your answer but I see no obvious reason to do that many allocations unless sizeof(Cell) * size * size is large enough to make a single allocation fail (but allocating smaller parts doesn't). I suggest doing one allocation only which gives a few benefits. In no particular order:

  • Faster allocation in most cases.
  • Faster access to the elements that will be tightly packed and therefore be more cache friendly.
  • Easier memory management - there is only one pointer to check and free.
  • Less total memory allocated than when allocating memory for a lot of pointers.

Example 1 - Make cells a pointer to the first of size number of elements of Cell[size].

// one allocation:
Cell (*cells)[size] = malloc( size * sizeof *cells );

if(cells == NULL) exit(1); // check for allocation failure

for(int i = 0; i < size; i++){
    for(int j = 0; j < size; j++){
        cells[i][j].p.y = i;
        cells[i][j].p.x = j;
        cells[i][j].value = 0;
    }
}

Example 2 - Make cells a pointer to a single Cell[size][size]:

// one allocation:
Cell (*cells)[size][size] = malloc( sizeof *cells );

if(cells == NULL) exit(1); // check for allocation failure

for(int i = 0; i < size; i++){
    for(int j = 0; j < size; j++){
        (*cells)[i][j].p.y = i;
        (*cells)[i][j].p.x = j;
        (*cells)[i][j].value = 0;
    }
}

Upvotes: 0

S Dao
S Dao

Reputation: 563

Additional:

for(i = 0; i < size; i++){
    for(j = 0; j < size; j++){
        Position p = {i,j};
        Cell c = {p, 0};
        cells[i][j] = &c; //This doesn't work
    }
    // to this line, 'c' & 'p' will be freed since it was allocated on stack not heap.
    // 'c' & 'p' will be freed when program gets out of 2nd for loop, so either you can
    // use memcpy to copy 'c' into cells[i][j] or use malloc to allocate 'c' and 'p'
}

Upvotes: 0

Barmar
Barmar

Reputation: 780724

I'm not sure why you say cells[i][j]->value = 0; doesn't work, I believe it should.

This should work to set all the members.

Cell ***cells = malloc(sizeof(Cell**) * size);
for(i = 0; i < size; i++){
    cells[i] = malloc(sizeof(Cell*) * size);
    for(j = 0; j < size; j++){
        cells[i][j] = malloc(sizeof(Cell));
        cells[i][j]->p.x = i;
        cells[i][j]->p.y = j;
        cells[i][j]->value = 0;
    }
}

Upvotes: 2

Related Questions