views:

188

answers:

1

In my data.h file I have:

typedef struct {
    double ***grid;
} Solver;

In my .c file I have

static Solver _solver;

which first makes a call to a function to do some allocation on grid such as

_solver.grid = malloc(....);

//then makes a call to

GS_init(_solver.grid);

The GS_init function is declared in GS.h as:

void GS_init(double ***grid);

When I try to compile, I get two errors:

the struct "<unnamed>" has no field "grid"
GS_init(_solver.grid)
^

and

too many arguments in function call
GS_init(_solver.grid)
^

Any ideas what is going wrong here?

+1  A: 

This code compiles with 'gcc -Wall -Werror -c':

data.h

typedef struct
{
    double ***grid;
} Solver;

gs.h

extern void GS_init(double ***grid);

gs.c

#include "data.h"
#include "gs.h"
#include <stdlib.h>

static Solver _solver;

void anonymous(void)
{
    _solver.grid = malloc(32 * sizeof(double));
    GS_init(_solver.grid);
}

Derek asked:

Why does this work? Is it because of the extern keyword?

The 'extern' is not material to making it work, though I always use it.

When I have to flesh out GS_init() in, say compute.c, would I write void GS_init(double ***grid){ //loop over grid[i][j][k] setting to zero }

Sort of...yes, the GS_init() code could do that if the data structure is set up properly, which is going to need more information than there is currently visible in the structure.

For the compiler to process:

grid[i][j][k] = 0.0;

the code has to know the valid ranges for each of i, j, and k; assume the number of rows in each dimension are Ni, Nj, Nk. The data 'structure' pointed to by grid must be an array of Ni 'double **' values - which must be allocated. Each of those entries must point to Nj 'double *' values. So, you have to do more allocation than a single malloc(), and you have to do more initialization than just setting everything to zero.

If you want to use a single array of doubles only, you will have to write a different expression to access the data:

grid[(i * Ni + j) * Nj + k] = 0.0;

And under this scenario, grid would be a simple double * and not a triple pointer.

Jonathan Leffler
why does this work? because of the extern keyword? when I have to flesh out GS_init() in, say compute.c, would i write void GS_init(double ***grid){ //loop over grid[i][j][k] setting to zero }
Derek
It should be `Ni` and `Nj`, not `Ni-1` and `Nj-1`.
BlueRaja - Danny Pflughoeft
@BlueRaja: yes, you're right; thanks. Too long since I had to do this sort of stuff.
Jonathan Leffler