Search code examples
data-structuresmultidimensional-arrayinitializationcalloc

Dynamic array inside dynamic structure array in c


I am stuck trying to figure out how to initialize a pointer to a 3d array inside a 2d structure array. I had it working fine when I could declare the structure like this:

    #define ROUSSEAU      300
    #define OSSO          500
    #define MOJO          9000

typedef struct x_primitive
{  
    short avg[ROUSSEAU][OSSO][MOJO];
} xprimitive;

But unfortunately the structure is too large to declare as a global. So I have to calloc the memory (192GB memory available on the system: win 7 64 bit);

typedef struct x_primitive
{  
    short ***avg;
} xprimitive;

xprimitive **xPmtv, *_xPmtv;


void xallocatePmtvMemory(void)
{
    int structureCount = 10;

    unsigned __int64 pmtvStructureSize =  ROUSSEAU * OSSO * MOJO * sizeof(short);
    unsigned __int64 memoryBlockSize   =   structureCount * pmtvStructureSize;

    _xPmtv = (xprimitive *)  calloc(structureCount, pmtvStructureSize);
    xPmtv  = (xprimitive **) calloc(structureCount, sizeof(xprimitive *));
    for ( int i = 0; i < structureCount; ++i)
    {
        unsigned __int64 index = i * pmtvStructureSize;
        xPmtv[i] = &_xPmtv[ index ];

            // **************** here is the problem  ******
        xPmtv[i]->avg[ROUSSEAU][OSSO][MOJO] =  &_xPmtv[ index + (ROUSSEAU + OSSO + MOJO) ];

    }
}

I am trying to assign the "avg" variable to a chunk of memory, and utterly failing.


Solution

  • Pointers and arrays aren't interchangeable in the way you seem to be wanting them to be. I think you can probably be doing something much simpler. Make avg into a pointer:

    typedef struct x_primitive
    {  
        short (*avg)[ROUSSEAU][OSSO][MOJO];
    } xprimitive;
    

    And then allocate the space for the array at runtime:

    xprimitive xPmtv;
    
    xPmtv.avg = calloc(1, ROUSSEAU * OSSO * MOJO * sizeof(short));
    

    Using it is a bit funny looking, though:

    (*xPmtv.avg)[1][2][3]
    

    If you have multiple structures, just throw the initialization into a loop. Maybe a better idea is to use a flexible array member to keep the usage syntax looking a bit more normal - it will cost you a dummy entry in the structure - flexible array members aren't allowed to play around on their own. Then again, why do you have a structure with only one field anyway?

    typedef struct x_primitive
    {
        int   dummyEntry;
        short avg[][OSSO][MOJO];
    } xprimitive;
    

    To allocate one, you'd use:

    xprimitive *xPmtv = calloc(1, sizeof(xprimitive) + ROUSSEAU * OSSO * MOJO * sizeof(short));
    

    And access the array something like:

    xPmtv->avg[1][2][3]