Search code examples
cfor-loopmultidimensional-arraymallocdouble-pointer

how to allocate memory dynamically for pointers and three dimensional arrays


I want to allocate memory dynamically using malloc so that i can use for loop to access each array and array element.

My code looks like this:

long naxes1[3]  = {1,1,1}, naxes2[3]  = {1,1,1}, naxes3[3]  = {1,1,1}, naxes4[3]  = {1,1,1}; //upto naxes20

Another line of code is:

double *pix1,  *pix2,  *pix3,  *pix4,  *pix5; //upto *pix20

To allocate the memory, I do this:

pix1  = (double *) malloc(npixels * sizeof(double));        
pix2  = (double *) malloc(npixels * sizeof(double));//20 times,

How can we use for loop to allocate memory for pixels instead of this?

moreover,

#include"cfitsio.h"
long        npixels = 1;
fits_read_pix(names[0], TDOUBLE, firstpix, npixels, NULL, pix1, NULL, &status)

here, names[i] are names of fitsfile inputs, TDOUBLE is double type, first pixels, npixels, etc are local variables inside C library routine cfitsio.h


Solution

  • When you have written variable names naxes1, naxes2, …, naxes20, you need to rewrite the code to use an array. If you need indexes 1..20, then you could write:

    int naxes[21][3] = { { -1, -1, -1 },  /* Element 0 - unused */
                         { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 },
                         { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 },
                         { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 },
                         { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 },
                         { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 },
                       };
    

    Or, using a very sensible and convenient GCC extension:

    int naxes[21][3] = { [0] = { -1, -1, -1 }, [1 ... 20] = { 1, 1, 1 }, };
    

    The range notation [1 ... 20] is the extension; the [0] = { -1, -1, -1 }, is standard C99 — a designated initializer.

    With this, you can use naxes[n][m] for n in the range 1..20 and m in the range 0..2 to access the elements of naxes.

    Similar comments apply to the pixN variables. However, there you want dynamic memory allocation; you might then use:

    double *pix_base = malloc(20 * npixels * sizeof(double));
    if (pix_base == 0) { …handle out of memory error… }
    
    double  pix[21];
    pix[0] = 0;
    for (int i = 1; i < 21; i++)
        pix[i] = pix_base + (i - 1) * npixels;
    

    You can now use pix[n][m] for n in the range 1..20 and m in the range 0..(npixels-1) to access the data. When finished, you call free(pix_base) to free all the memory at once. This is more economical on space than 20 separate memory allocations (and more economical on calls to malloc() and free()).

    You can adapt this second technique to handle the arrays of integers too.

    If you can use entries 0..19 instead of 1..20, then you can save a little complexity.