简体   繁体   中英

Passing a Structure by reference to a function that will dynamically create and fill a array of structures

I want to pass a structure pointer to a function that will dynamically create a array of structures at the location pointed to by the structure pointer that was passed. I am able to create and fill the array of structure successfully but when trying to print the data in the calling function using the pointer that was passed gives me a garbage values. Please help me know why my structure pointer is pointing to garbage and how can I access my data correctly.

The following is just some example code to demonstrate how the structure is passed and dynamically filled using malloc & realloc. this is INCORRECT method:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student 
{
    int id;
    char name[20];
    float percentage;
};

void func(struct student *record);

int main() 
{
    struct student *record = NULL;

    record = (struct student *)malloc(sizeof(struct student));

    func(record);

    if(record != NULL)
    {
        for(int i=0; i<2; i++)
        {
            printf(" 1 Id is: %d \n", record[i].id);
            printf(" 1 Name is: %s \n", record[i].name);
            printf(" 1 Percentage is: %f \n", record[i].percentage);
            printf("\n");
        }
    }
    else
    {
        printf("record pointer is null");
    }

    return 0;
}

void func(struct student *record1)
{
    for(int i=0; i<2; i++)
    {
        if(i)
        {
            record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));
        }
        record1[i].id=1;
        strcpy(record1[i].name, "Raju");
        record1[i].percentage = 86.5;
    }
}

The following is a similar example using double pointer which is the CORRECT way to do this:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct student 
{
    int id;
    char name[20];
    float percentage;
};

void func(struct student **record);

int main() 
{
    struct student *record = NULL;

    func(&record);

    if(record != NULL)
    {
        for(int i=0; i<2; i++)
        {
            printf(" 1 Id is: %d \n", record[i].id);
            printf(" 1 Name is: %s \n", record[i].name);
            printf(" 1 Percentage is: %f \n", record[i].percentage);
            printf("\n");
        }
    }
    else
    {
        printf("record pointer is null");
    }

    free(record);

    return 0;
}

void func(struct student **record1)
{
    *record1 = (struct student *)malloc(sizeof(struct student));
    for(int i=0; i<2; i++)
    {
        if(i)
        {
            *record1 = (struct student *)realloc(*record1,sizeof(struct student)*(i+1));
        }
        (*record1)[i].id=1;
        strcpy((*record1)[i].name, "Raju");
        (*record1)[i].percentage = 86.5;
    }
}

Your first solution,

record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));

works as long as realloc does not have to move the pointer! That is, realloc just expands the memory area it gave earlier to record1 . Should, at some later stage, realloc be required to give you another piece of memory, then the earlier pointer record in main will become invalid and could now contain your "garbage".

As you were thinking, you need a double pointer to be able to see the changed pointer in main . You were nearly there, just a typo:

*record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));

in the above line the second occurrence of record1 must also be dereferenced, so *record1 because you must give realloc the original pointer.

Oh, and don't cast the result of malloc! Although the compiler does not complain, it can cause future problems.

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