You don't need to do multiple levels of memory allocation. This is perfect for the use a flexible array member:
typedef struct
{
unsigned length;
ElemType data[];
} SqList;
To allocate, use something like this:
SqList *allocateList( unsigned length )
{
SqList *list = malloc( sizeof(*list) + length * sizeof(list->data[0]));
if ( list )
{
list->length = length;
}
return( list );
}
Reallocation to a new size:
SqList *reallocateList( SqList *origList, unsigned newLen )
{
unsigned origLen = origList->length;
SqList *newList = realloc( origList,
sizeof(*newList) + newLen * sizeof(newList->data[0]));
if ( newList )
{
newList->length = newLength;
// initialize new elements - origLen
// is already at the start of any
// new data elements
for ( ; origLen < newLen; origLen++ )
{
newList->data[ origLen ] = -1;
}
}
return( newList );
}
Free a list:
free( list );
Explanation:
A structure with a flexible array member is allocated as a single variable-sized chunk of memory. The first elements of the allocated memory are fixed, as in a normal structure. The last "flexible" element is an array of variable size. Thus the structure and its variable amount of actual data are both allocated at one time.
Conversely, a structure that contains a pointer to a variable-size array must be allocated in two steps - one allocation for the structure itself, and another for the data array.
When using dynamic allocation, flexible array members make for much simpler code. The downside is using structures with flexible array members as "normal" local variables has issues. For example, given
typedef struct
{
unsigned length;
ElemType data[];
} SqList;
this code is problematic:
void someFunc( void )
{
SqList list;
.
.
.
}
Where's the data element? It doesn't really exist, and there's no way to allocate a data element for such a structure given that example code. You could use alloca()
for the entire structure including the data element, but that can cause problems if the code is in a loop.