简体   繁体   中英

C how to modify memory of structs that are inside other structs

If I have two structs:

typedef struct{
    unsigned int time;
    double rate;

}quote;

typedef struct{

    unsigned int freeSlots;
    unsigned int end;
    unsigned int start;
    unsigned int currSize;
    unsigned int maxSize;
    unsigned int startAt;
    //unsigned int currIndex;
    quote quoteBuffer[1];

}cbuf;

And I wanted to make a function that would modify the size of the quoteBuffer array inside cbuf, how exactly would I go about doing that? I have tried a few approaches but none have worked so far. I keep returning to the same format of:

quote *newQuoteBuffer = malloc(sizeof(quote) * newSize);

And if I already have an existing cbuf somewhere (for example, we will call it "a" where a is the pointer to the cbuf):

a->quoteBuffer = newQuoteBuffer;

But obviously this doesn't work. Any hints?

This:

quote quoteBuffer[1];

should be:

quote *quoteBuffer;

Then the assignment will work.

Dereferencing quote looks like this:

a->quoteBuffer->time;

If you later have multiple elements of quote allocated with malloc() you can access them like this:

a->quoteBuffer[i].time;

If you are not sure of how many elements will go into the quoteBuffer, maintain a linked list of the same. For that

quote *quoteBuffer;

And keep adding or removing the elements to/from the buffer as required.

I think you're missing the point of why someone would have the last element of a struct as a single element array. This is a trick that's used in old C code as a way to make the struct size variable length.

You can write code such as this:

Bitmapset *p = malloc(offsetof(Bitmapset, quoteBuffer) + n * sizeof(quote));

Then you write code like this:

p->quoteBuffer[0]

up to:

p->quoteBuffer[n-1]

You do not want to assign a pointer directly to quoteBuffer, as you guessed.

So, why would you want to declare quoteBuffer as: quote quoteBuffer[1]; instead of quote* quoteBuffer; ?

It's because you do not wanna to have a separate allocation for quoteBuffer. A single allocation can be used for the entire cbuf, including the inline quote array.

There are two approaches. One is to use a pointer in cbuf, as others have mentioned, by changing

quote quoteBuffer[1];

to

quote* quoteBuffer;

The other is to resize the cbuf:

#include <stddef.h> // for offsetof

struct cbuf* realloc_cbuf(struct cbuf* cbufp, size_t nquotes)
{
    struct cbuf* new_cbufp = realloc(cbufp, offsetof(struct cbuf, quoteBuffer) + nquotes * sizeof *cbufp->quoteBuffer);
    if (!new_cbufp)
    {
        // handle out of memory here. cbufp is still intact so free it if you don't need it.
    }
    return new_cbufp;
}

void elsewhere(void)
{
    struct cbuf* acbuf = NULL;
    acbuf = realloc_cbuf(1);
    acbuf = realloc_cbuf(10);
    // etc. 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM