Issues
Design
I am trying to use an array of pointers to a struct that has a pointer in it to another struct that is being used with an array of pointers.
In other words, we must find a way to design "An array of pointers to a struct, which contains a pointer to another struct used as an array".
I will focus on this.
Array of pointers
However, I am not sure how to deal with the introduction of the array of pointers.
Well, we don't have any array of pointers in your code... you must create one first.
C pointers, arrays, structures and all their combinations have countless threads all over the internet which have been answered several times. I will show you a few basic examples so you can be up and running, just don't expect me to give you a whole lesson of pointers.
Solutions
Design
Here is the code (I changed some variable names to make it more readable):
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double value;
}Particle;
typedef struct
{
int width;
int height;
Particle *particles;
}Grid;
Grid *createGrid(int width, int height)
{
Grid *result = malloc(sizeof(Grid));
if (result == NULL)
{
printf("Error while allocating memory for the grid structure!\n");
exit(1);
}else
{
result->width = width;
result->height = height;
result->particles = malloc(sizeof(Particle) * width*height);
}
return result;
}
void destroyGrid(Grid *grid)
{
free(grid->particles);
free(grid);
}
int main()
{
Grid *grids[3];
for (int i = 0; i < 3; i++)
grids[i] = createGrid(5, 3);
/* Assign, modify, read or copy values from the array of pointers here */
for (int i = 0; i < 3; i++)
destroyGrid(grids[i]);
return 0;
}
As you can see, I introduced 2 functions to make your life easier: createGrid and destroyGrid.
The first one will need you to specify 2 arguments: the width
and height
(m
and n
in your code) of a grid. The function is then going to allocate memory and return a pointer to the grid it just created.
The second one will need you to specify 1 argument: a pointer to a grid. The function is then going to free all the memory the first function allocated, avoiding any memory leaks.
I've also added an array of pointers in the main function: grids
. This, in combination with the usage of the functions described above (all in the main function), solves the first issue.
The final design can be read as follows:
"We have an array of pointers to a struct (grids
), which contains a pointer to another struct (particles
) which should be used as an array".
Array of pointers
You may be wondering now: "OK, so how am I supposed to use this array-of-pointers-to-a-structure-confusing-stuff?" As I said before, I will show you a practical example only.
Lets assume you want to set the value of the third particle of the first grid to 2.7182: (you should insert this code in the place I commented as /* Assign, modify, read or copy values from the array of pointers here */
)
grids[0]->particles[2].value = 2.7182;
And this can be read, from left to right, as: "From the array of pointers grids
, get the element with index 0 (the first pointer to a Grid
structure). Access its structure member particles
, which is a pointer. Treat that pointer as an array and get the element with index 2 (the third Particle
structure). Access its member value
and assign to it the value 2.7182"
You could then do something like copy one particle to another:
grids[1]->particles[1] = grids[0]->particles[2];
Here are some links to better understand pointers, arrays and structs. Practice and experimentation is the best way to deal with them:
Update
I realized that what I should be doing is use the inparticles pointer to point to multiple particles in the same grid pointer
I need to use a separate array of pointers to particles. The array inside the grid structure is only to point to a subset of particles.
Objective: "Use the inparticles pointer to point to a subset of multiple (sequential or non-sequential?) particles (which are being managed somewhere else)".
If you want the sequential solution you could use a pointer, representing a pointer to the base address (or offset, if you want only a subset) of an array (this is, a pointer to an array). This has the advantage of not needing you to allocate extra memory for every single pointer (since only the base address is necessary), but it has the disadvantage that you can only access particles that are next to each other.
Example:
typedef struct
{
int width;
int height;
Particle *subparticles; //Represents a pointer to an array subset
}Grid;
/*...*/
grids[0]->subparticles = &particles[0];
grids[1]->subparticles = &particles[1];
printf("%f equals %f", grids[0]->subparticles[1].value, grids[1]->subparticles[0].value);
/*...*/
However, If you want the non-sequential solution, you could use a double pointer (representing an array of pointers) while having to manually allocate memory for the array. This provides you with more flexibility, but comes at the price of memory allocation overhead.
typedef struct
{
/*...other members...*/
Particle **subparticles;
}Grid;
Grid *createGrid(int subparticlesCount)
{
Grid *result = malloc(sizeof(Grid));
if (result == NULL)
{
printf("Error while allocating memory for the grid structure!\n");
exit(1);
}else
{
result->subparticles = malloc(sizeof(Particle *) * subparticlesCount);
}
return result;
}
/*...*/
grids[0]->subparticles[0] = &particles[1];
grids[0]->subparticles[1] = &particles[5];
grids[0]->subparticles[2] = &particles[3];
grids[1]->subparticles[0] = &particles[3];
printf("%f equals %f", grids[0]->subparticles[2]->value, grids[1]->subparticles[0]->value);
/*...*/