user3419585
user3419585

Reputation: 13

Writing to Dynamic Memory

I have the following pointer to structure

struct ALIST                     
{
    short sPeriod;
    long lDate;
}*list_ptr;

list_ptr = malloc(sizeof(*list_ptr));

Now if I have a global variable sIndex which I initialize to zero, is it possible to do this?

(list_ptr + sIndex)->sPeriod = period_variable;
(list_ptr + sIndex)->lDate = date_variable;
sIndex++

Is there a more efficient method?

Upvotes: 0

Views: 82

Answers (2)

Zan Lynx
Zan Lynx

Reputation: 54325

This looks like you want to allocate a dynamic array. Make a size variable and set it to your starting size for the array.

Something like:

size_t list_size = 10;
struct ALIST list_ptr = 0;
size_t i;    

list_ptr = malloc(sizeof(*list_ptr) * list_size);
for(i=0; i<list_size; ++i) {
    list_ptr[i].sPeriod = period;
    list_ptr[i].lDate = date;
}

Now, if you don't know the size of the array then what you want ends up looking a lot like a C++ std::vector.

I'd build a C version that wraps the necessary information in a struct. Use realloc to resize it.

It might look like (NOTE THAT THIS IS COMPLETELY UNTESTED):

struct dynamic_ALIST {
    struct ALIST *array;
    size_t size;
    size_t capacity;
};

void dynamic_ALIST_construct(struct dynamic_ALIST *x, size_t initial_size)
{
    x->array = 0;
    x->size = 0;
    x->capacity = 0;
    dynamic_ALIST_reserve(x, initial_size);
}

void dynamic_ALIST_reserve(struct dynamic_ALIST *x, size_t size)
{
    struct ALIST *tmp = realloc(x->array, sizeof(*tmp) * size);
    if(!tmp) abort();
    x->array = tmp;
    x->capacity = size;
}

struct ALIST* dynamic_ALIST_get(struct dynamic_ALIST *x, size_t offset)
{
    if(offset < x->size) {
        return x->array + offset;
    }
    if(offset < x->capacity) {
        x->size = offset + 1;
        return x->array + offset;
    }
    dynamic_ALIST_reserve(x, offset+1);
    return dynamic_ALIST_get(x, offset);
}

Then you could use it like:

void f()
{
    size_t item_index = 0;
    struct dynamic_ALIST list;
    FILE *fp = fopen("filename");

    dynamic_ALIST_construct(list, 0);
    while( read_item(fp, dynamic_ALIST_get(list,item_index)) ) {
        item_index++;
    }
    fclose(fp);
}

You can make all kinds of changes to that. The get function might return an error instead of automatically creating new entries. You might make another function that increases the size. You might want to have a function that sets all the values to zero before returning new memory.

If you have a lot of different structs to wrap up you can put ALL of the above dynamic_ALIST struct, and construct, reserve, get functions into a macro. If you do it right then you just say:

NEW_DYNAMIC_STRUCT(ALIST);

And the preprocessor spits out a whole new copy with all the names changed.

Upvotes: 1

brokenfoot
brokenfoot

Reputation: 11609

I'll answer point by point:

  1. Do those pointer manipulations only if you know what you are doing.

  2. Assuming sIndex to be an int, with sIndex=0;, it is no problem but if you increment sIndex, you don't have that space allocated to use becuase you have malloc'd just one block.

  3. You need to first do your allocation appropriately if you need to access multiple such blocks then:

    list_ptr = malloc(sizeof(struct ALIST)*N); //replace N with the number of blocks you want

Upvotes: 0

Related Questions