0

I want to insert the Set_b's element to the Set_a list when the Set_a don't contain it.What I mean is like that {1, 2, 3} ∪ {3, 4, 5} = {1, 2, 3, 4, 5}.

typedef struct
{
   ElemType data[MAXSIZE];
   int length;
}SqList;

But at first, when I want to create a new list, I came across a compiling warning: assignment makes integer from pointer without a cast:

 void CreateList(SqList *L)
{


   L->data[0] = (int*)(ElemType*)malloc(sizeof(int)*20);

   L->length = 0;
}

I tried to change the L->data[0] to others, but it turned into an error.

Ghoster
  • 75
  • 10

2 Answers2

2

The space of data is already allocated. You may want to do something like this instead:

typedef struct
{
   ElemType *data;
   int length;
}SqList;

And then perform the memory allocation:

L->data = (ElemType*)malloc(sizeof(ElemType)*20);

Actually, there is no need to cast the return value of malloc() to ElemType *. The following statement will do:

L->data = malloc(sizeof(ElemType)*20);

Extending memory dynamically

You could define the structure consisting of two parts for storing data:

  1. An array of ElemType. Fixed size. No need for dynamic memory allocation. All instances of SqList can contain up to INITIAL_SIZE elements without dynamically allocating memory.
  2. A pointer to ElemType. It provides the possibility of increasing the number of elements you can store at run-time.

    typedef struct
    {
       ElemType data[INITIAL_SIZE]; // always allocated
       ElemType *ext; // it's up to you whether allocate this or not
       size_t length;
    } SqList;
    

Whenever you need to allocate more memory on a SqList, you could use the following function:

// Extends the number of elements the given SqList can hold in num_elems elements
ElemType* SqList_extend(SqList *p, size_t num_elems) {
   if (p->ext) // memory already allocated?
      return NULL; // then release it first

   // perform allocation
   if ((p->ext = malloc(sizeof(ElemType) * num_elems))) // successful?
      p->length += num_elems; // then increase the element count
   return p->ext; // return a pointer to the new allocated memory
}
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • 2
    [Please don't cast `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Daniel Kamil Kozar May 18 '17 at 17:43
  • @Neroku, it's still an error: assignment to expression with array type. The L->data is an array 'data[20]' in the declaration. – Ghoster May 19 '17 at 00:15
  • @Ghoster why not just to include an already-allocated array for 20 elements and an additional pointer for dynamic extension? – JFMR May 19 '17 at 03:56
1

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.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • Thank you! it's a great help to me.But the creatList function should also be used for creating a new one.And there is still a running error that it displays in a mess and quit.And in the main function, the CreatList is used like that CreateList(&LA); The List is a const SqList – Ghoster May 19 '17 at 01:09
  • @Ghoster You're making this more complex than it needs to be. In general, every time you use a pointer, you have to do the allocations and freeing yourself. If you make `list->data` a *pointer* you need to do two allocations - one for the structure itself, and then one for the data. If you use a flexible array element, you only need to do one allocation. The only potential issue with flexible array members might be using the structure as a local variable. – Andrew Henle May 19 '17 at 09:21