1

I have an assignment of dynamic allocation for an array of structs. I'm having trouble to understand/explain why I need pointer to pointer and not like with regular array only pointer, Maybe someone can explain? The code as following i added the whole code including main function.

struct Date {
    int year;
    int month;
    int day;
};

struct Student {
    char name[100];
    float grades;
    float points;
    int id;
    struct Date birth_date;
};

struct Student** get_student_data(int* number_of_student)
{
    printf("how many students in your class? ");
    scanf("%d", number_of_student);

    struct Student** student_pointers_array = malloc(sizeof(struct Student*) * *number_of_student);
    if (student_pointers_array == NULL)
        return;
    struct Student* student_array = malloc(sizeof(struct Student) * *number_of_student);
    if (student_array == NULL)
        return;
    for (int i = 0; i < *number_of_student; i++)
    {
        printf("Enter Name\n");scanf(" %[^\n]s", &student_array[i].name);
        printf("Enter Grades\n");scanf("%f", &student_array[i].grades);
        printf("Enter Points\n");scanf("%f", &student_array[i].points);
        printf("Enter ID\n");scanf("%d", &student_array[i].id);
        printf("Enter year\n");scanf("%d", &student_array[i].birth_date.year);
        printf("Enter month\n");scanf("%d", &student_array[i].birth_date.month);
        printf("Enter day\n");scanf("%d", &student_array[i].birth_date.day);
        student_pointers_array[i] = &student_array[i];
    }

    return student_pointers_array;
}
void print_student_data(struct Student** student_data, int number_of_student)
{
    for (int i = 0; i < number_of_student; i++)
    {
        printf("name: %s\n", student_data[i]->name);
        printf("average: %f\n", student_data[i]->grades);
        printf("academic points: %f\n", student_data[i]->points);
        printf("ID: %d\n", student_data[i]->id);
        printf("birth year: %d\n", student_data[i]->birth_date.year);
        printf("birth month: %d\n", student_data[i]->birth_date.month);
        printf("birth day: %d\n", student_data[i]->birth_date.day);
    }
}

void main()
{
    int number_of_student = 0;
    struct Student** student_data = get_student_data(&number_of_student);
if (student_data == NULL)
        return;
    print_student_data(student_data, number_of_student);
    free(student_data);
}

4
  • We can do with anything * or **, depends on what we need to store where Commented Dec 30, 2020 at 5:43
  • If you return a struct Student *, you don't need the student_pointers_array at all. Your compiler should not let you write return; in a function defined to return a pointer value. You should use return NULL: probably. Commented Dec 30, 2020 at 5:54
  • I added more detailed code, i just want to understand the solution and the theory behind it. Commented Dec 30, 2020 at 6:01
  • void main() is wrong on anything other than Windows, and not recommendable even there (AFAIAC). Your free(student_data) leaks memory — you need to delete the other memory allocation too (free(student_data[0]) should do the job, I believe). Commented Dec 30, 2020 at 6:04

1 Answer 1

2

You don't need to use struct Student ** — you can use a single level of pointers, like this:

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

struct Date
{
    int year;
    int month;
    int day;
};

struct Student
{
    char name[100];
    float grades;
    float points;
    int id;
    struct Date birth_date;
};

static
struct Student *get_student_data(int *number_of_student)
{
    printf("how many students in your class? ");
    scanf("%d", number_of_student);

    struct Student *student_array = malloc(sizeof(struct Student) * *number_of_student);
    if (student_array == NULL)
        return NULL;
    for (int i = 0; i < *number_of_student; i++)
    {
        printf("Enter Name\n");
        scanf(" %[^\n]s", student_array[i].name);
        printf("Enter Grades\n");
        scanf("%f", &student_array[i].grades);
        printf("Enter Points\n");
        scanf("%f", &student_array[i].points);
        printf("Enter ID\n");
        scanf("%d", &student_array[i].id);
        printf("Enter year\n");
        scanf("%d", &student_array[i].birth_date.year);
        printf("Enter month\n");
        scanf("%d", &student_array[i].birth_date.month);
        printf("Enter day\n");
        scanf("%d", &student_array[i].birth_date.day);
    }

    return student_array;
}

static
void print_student_data(struct Student* student_data, int number_of_student)
{
    for (int i = 0; i < number_of_student; i++)
    {
        printf("name: %s\n", student_data[i].name);
        printf("average: %f\n", student_data[i].grades);
        printf("academic points: %f\n", student_data[i].points);
        printf("ID: %d\n", student_data[i].id);
        printf("birth year: %d\n", student_data[i].birth_date.year);
        printf("birth month: %d\n", student_data[i].birth_date.month);
        printf("birth day: %d\n", student_data[i].birth_date.day);
    }
}

int main(void)
{
    int number_of_student = 0;
    struct Student* student_data = get_student_data(&number_of_student);
    if (student_data != NULL)
    {
        print_student_data(student_data, number_of_student);
        free(student_data);
    }
    return 0;
}

This simplifies the memory release, too. The code in the question leaks the array of structures (it only frees the array of pointers).

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, so what was the rational of using pointer to pointer in the first place? To use '->' syntax? or is there any other rational stands behind the solution?
I can see no good reason for using the array of pointers as well as the array of structures. If each structure was allocated separately, then you'd need an array of pointers too, but with all the structures allocated at once, there was no benefit and some disadvantage to using the two arrays.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.