Search code examples
cpointersmemory-managementstructdynamic-memory-allocation

Allocating and reallocating a struct and its elements


I have a few questions about allocating memory to structs and their members.

Suppose I have a struct like this:

struct _MyStruct
{
    char *a;
}
typdef struct _MyStruct MyStruct;
  1. I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case? Example:

    MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
    MyStruct *myStrCopy = myStr;
    myStrCopy->a=malloc(sizeof(char));
    //checking for null//
    
  2. Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?

  3. Can I allocate more memory to 'a' than I allocated to myStr?

  4. Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?


Solution

    1. I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case?

    Well, your MyStruct always needs to exist, but there are several ways to do this and you should go for the simplest one that fits your use case.

    Basic approach:

    MyStruct myStr;
    myStr.a = malloc(N); // "N chars please!"
    
    // You can still get a pointer to this object:
    foo(&myStr);
    
    // Don't forget to free the `char` buffer later
    free(myStr.a);
    

    Dynamic allocation — valid, but not inherently necessary:

    MyStruct* myStr = malloc(sizeof(MyStruct));
    myStr->a = malloc(N); // "N chars please!"
    
    // It's already a pointer, so:
    foo(myStr);
    
    // Don't forget to free the `char` buffer later
    free(myStr->a);
    
    // And then the struct
    free(myStr);
    
    1. Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?

    It's a new block.

    Each block of dynamically allocated memory is entirely separate. When you made the member variable a a pointer, you ensured that although a lives within the struct, the thing it points to does not (unless you make it point to itself, lol).

    myStr (or *myStr):                       your malloc'd memory:
    
    0          32                       0   8   16   24   32   40  ...
    +----------+                        +------------------------------+
    | char* a——|———————————————————————→| text or whatever here        |
    +----------+                        +------------------------------+
     (somewhere in memory)                 (somewhere else in memory)
    

    The above diagram is valid no matter which way you constructed myStr.

    1. Can I allocate more memory to 'a' than I allocated to myStr?

    Yeah, whatever you want. It's separate. You have indirection.

    1. Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?

    No.