Home > Net >  How to allocate memory for structure?
How to allocate memory for structure?

Time:05-26

I'm learning C. I have a structure, and if I need to set array of structures -> so I allocate memory for this array. But do I need separately allocate memory for fields in this structure? Like this:

struct Call{
    char *country;
    int duration;
};

int main(){
    struct Call *calls;
    int n;
    scanf_s("%d", n);
    calls = (struct Call *) calloc(n 1 , sizeof(struct Call));
}

CodePudding user response:

You need not to allocate space for data members of objects of the structure type because they belong to the objects.

But it seems you will need to allocate a character array the pointer to which will be stored in the data member country if you want that objects will be owners of the corresponding strings.

For example

struct Call *calls = calloc( 1, sizeof( struct Call ) );
const char *country = "Some country";

calls->country = malloc( strlen( country )   1 );
strcpy( calls->country, country );

When you will deallocate memory for objects of the type struct Call you will need at first to free the memory allocated for character arrays pointed to by data members country.

CodePudding user response:

Yes, you must initialize any pointer before you can dereference it. This means allocating memory for it, or assigning it to already-allocated memory. That's a universal rule in C, there's no special cases for pointers in structures. C will not "recursively" allocate memory for you. Among other things, how would it know how much you need? Consider your simplified code below

int main(){
    struct Call *calls;
    calls = calloc(1 , sizeof(struct Call));
}

Assuming calloc succeeded, calls now points to a memory block that contains space for a single struct Call, which includes space for the char pointer and int. However, country itself is still an unintialized pointer, and you must allocate space for it or point it to something already-allocated before you can safely dereference it

calls->country = malloc(25);
if (calls->country == NULL) exit(-1);  // handle error how you want
strcpy(calls->country, "Portugal");
printf("%s\n", calls->country);  // prints Portugal

or something like

char myCountry[] = "Spain";
calls->country = myCountry;
myCountry[0] = 'X';
printf("%s\n", calls->country); // prints Xpain

Also see Do I cast the result of malloc?

CodePudding user response:

You need to allocate space for the struct and for char array.

You probably want to dynamically add calls to the array so you need to know the size of the array as well:

typedef struct Call{
    char *country;
    int duration;
}Call;


typedef struct
{
    size_t size;
    Call call[];
}Calls_t;


Calls_t *addCall(Calls_t *calls, const int duration, const char *country)
{
    size_t newsize = calls ? calls -> size   1 : 1;
    calls = realloc(calls, sizeof(*calls)   newsize * sizeof(calls -> call[0]));

    if(calls)
    {
        calls -> size = newsize;
        calls -> call[newsize - 1].country = malloc(strlen(country)   1);
        if(!calls -> call[newsize - 1].country) 
        {
            /* error handling */
        }
        strcpy(calls -> call[newsize - 1].country, country);
        calls -> call[newsize - 1].duration = duration;
    }
    return calls;
}

void printCalls(const Calls_t *calls)
{
    if(calls)
        for(size_t i = 0; i < calls -> size; i  )
            printf("Call %zu: Country:%s Duration:%d\n", i   1, calls -> call[i].country, calls -> call[i].duration);
}

int main(void)
{
    Calls_t *calls = NULL, *tmp;

    tmp = addCall(calls, 10, "Poland");
    if(tmp) calls = tmp;
    tmp = addCall(calls, 20, "UK");
    if(tmp) calls = tmp;
    tmp = addCall(calls, 30, "US");
    if(tmp) calls = tmp;

    printCalls(calls);
    /* free allocated memory */
}

https://godbolt.org/z/Kb5bKMfYY

  • Related