1. ## A quick question about pointers.

Hi there,

I have a quick question about a code I'm trying to understand. I see strange declarations in the code that involve 2 or 3 asterisks. Please see below (under /*Global declarations/*).

Here is the example code:

Code:
```#include "headers/chemistry.h"

/* Global declarations */

CELL ***cell;
FLUX **x1_fluxes, *x2_fluxes, x3_fluxes;

int temp_nx_cells, temp_ny_cells, temp_nz_cells, nx_cells, ny_cells,
nz_cells, rtnewt_check, t_index, x_index, y_index, z_index, **proc_lwrb;
int equal_gamma=1, finished=0, rank, n_proc_1, n_proc_2, n_proc_3, nproc,
lower_x2_bdry, lower_x1_bdry, lower_x3_bdry, nx_cells_tot,
ny_cells_tot, nz_cells_tot, x1_position, x2_position, x3_position,
low_x1_nbr, high_x1_nbr, low_x2_nbr, high_x2_nbr, low_x3_nbr, high_x3_nbr;
long int cell_counter=0;```
Would someone be able to explain their meaning and function to me?

Cheers,

Wayne.

2. >> CELL ***cell;

Pointer-to a pointer-to a pointer-to a CELL, called cell. As for how this pointer is actually used in the code, it's difficult to say with certainty.

>> FLUX **x1_fluxes, *x2_fluxes, x3_fluxes;

x1_fluxes is a pointer-to a pointer to a FLUX, x2_fluxes is a pointer to a FLUX, and x3_fluxes is a FLUX. Again though, it's tough to tell you how these are used. You would have to ask a better question; show us more what's going on, where your problem might be.

3. Pointer to pointer is usually associated to assign a value to a pointer.
Like say, you pass in a pointer to a function which that functions needs to assign. So it needs a pointer to that pointer, becoming a pointer to pointer.

4. Cheers, you explanation is excellent. I really wasn't sure what the *** actually did.

The code is quite big 500kb of source. I found it in the code at a later time used in memory allocation, I don't know does this help you understand further what is happening:

Note: The code is a numerical simulation, it's a 3d code, so cells just refers to the 3d cell in question on the grid. the flux is just the amount of heat or material etc. flowing through a face of a cell.

Code:
```if(rank == MASTER)
printf("Allocating memory\n");

cell=(CELL ***)calloc(nx_cells+2,sizeof(CELL **));
testdiss=(double ***)calloc(nx_cells+2,sizeof(double **));
inith2=(double ***)calloc(nx_cells+2,sizeof(double **));
temp=(double ***)calloc(nx_cells+2,sizeof(double **));
cooling=(double ***)calloc(nx_cells+2,sizeof(double **));
cv=(double ***)calloc(nx_cells+2,sizeof(double **));
subarray=(double ***)calloc(nx_cells+2,sizeof(double **));
initp=(double ***)calloc(nx_cells+2,sizeof(double **));
initden=(double ***)calloc(nx_cells+2,sizeof(double **));
init_source1=(double ***)calloc(nx_cells+2,sizeof(double **));
init_source2=(double ***)calloc(nx_cells+2,sizeof(double **));

for(i=0;i<nx_cells+2;i++){
cell[i]=(CELL **)calloc(ny_cells+2,sizeof(CELL *));
testdiss[i]=(double **)calloc(ny_cells+2,sizeof(double *));
inith2[i]=(double **)calloc(ny_cells+2,sizeof(double *));
temp[i]=(double **)calloc(ny_cells+2,sizeof(double *));
cooling[i]=(double **)calloc(ny_cells+2,sizeof(double *));
cv[i]=(double **)calloc(ny_cells+2,sizeof(double *));
subarray[i]=(double **)calloc(ny_cells+2,sizeof(double *));
initp[i]=(double **)calloc(ny_cells+2,sizeof(double *));
initden[i]=(double **)calloc(ny_cells+2,sizeof(double *));
init_source1[i]=(double **)calloc(ny_cells+2,sizeof(double *));
init_source2[i]=(double **)calloc(ny_cells+2,sizeof(double *));
for(j=0;j<ny_cells+2;j++){
cell[i][j]=(CELL *)calloc(nz_cells+2,sizeof(CELL));
testdiss[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
inith2[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
temp[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
cooling[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
cv[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
subarray[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
initp[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
initden[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
init_source1[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
init_source2[i][j]=(double *)calloc(nz_cells+2,sizeof(double));
}```
I had a look through the header files for this and found the following:

Code:
```extern CELL average(CELL , double, CELL , double, CELL , double);
extern CELL extrapolate(CELL , double, CELL , int);```
Thanks for your help with my question, it is much appreciated.

Wayne.

5. Yes, in this case, it's used for a dynamic 3D array.
First is allocates an array of pointer-to-pointers (**), and since it's calloc, it returns a pointer to the memory on the heap. That's one.
Next, for each of these pointers, it allocates another array of pointers (*) and stores them in the pointer to pointers (**). That's two.
And lastly, it allocates the actual space for the actual data and stores it in the pointers (*).

6. Yes, that is fairly typical 3D memory allocations for dynamic dimensioning of arrays. Since C (and C++) essentially only supports arrays of "size known at compile time"[1, 2], the only way to work around that is to have the code itself allocate the memory for the content of the arrays.

[1] Yes, I know some compilers support various forms of "dynamic" arrays.
[2] The constraint on "size know at compile time" is so that the compiler can arrange for the memory "behind" the array to be correctly sized. Of course, if the compiler "doesn't know", then it won't be able to arrange for the right amount of memory. To do this at runtime would require similar code to be generated by the compiler - and the language architects decided not to support this type of functionality in the current standard of the language.

--
Mats

7. Thank again for your fast reply, that explains it perfectly. Thanks a million for your help.

All the best,

Wayne.