简体   繁体   中英

How to fix my code to return a pointer to a struct from a function

I'm learning pointers and struct now and I'm a bit confused. Particularly, I want to make a function which returns a pointer to a struct. My code is compiling, but it isn't working. After I type the number of students, it asks for name and age (without reading name), and after I type the age, it closes.

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

struct details
{
    char name[100];
    int age;
};

struct details * details_pointer(int n)
{
    struct details pointer_x[n];
    struct details *pointer = pointer_x;
    for (int i=0; i<n; i++)
    {
        printf("Student %d:\n", i);
        printf("name:\n");
        fgets(pointer[i].name, 100, stdin);
        printf("age:\n");
        scanf("%d", pointer[i]. age);
    }
    return pointer;
}

int main()
{
    int n;
    printf("Type the number of persons:\n");
    scanf("%d", &n);
    struct details *student = details_pointer(n);
    printf("\nName: %s\n", (*student).name);
    printf("Age: %d\n", (*student).age);
    system("pause");
    return 0;
}

The problem here is that you're returning a structure variable ( pointer_x ) that's allocated locally on the stack of the inner details_pointer() function, but this memory is no longer reserved for you once it returns. This means you get (at best) garbage.

You have to either allocate memory in the function and return it (and remember to free it.) or pass the data to the function to fill it in.

void get_details(int n, struct details p[n])
{
  for (int i = 0; i < n; i++)
  {
    // do stuff with p[i]
  }
}

int main()
{
   ...
   scanf("%d", &n);
   struct details students[n];
   get_details(n, students);

   printf("\nName: %s\n", students[0].name);
   ...
}

I generally prefer passing data to the function when possible just because it simplifies memory management.

EDIT: Two notes about your existing details_pointer() function.

1) In fgets(pointer[i].name, 100, stdin) , it's a good practice to derive the number of bytes from the size of the array if it's known; in this case it is, so recommend fgets(pointer[i].name, sizeof(pointer[i].name), stdin) . Yours is not incorrect, but it's easier to maintain should the sizes change in the future.

2) the scanf("%d", pointer[i].age) needs to take the address of the .age to stuff its value in there; you're passing a number instead of an address, which is for sure incorrect.

Ok, so if the assignment requires dynamic allocation, then that's what we have to do.

Just specifying an array implicitly allocates the space while the function is running, but it disappears when the function returns. You'll need to allocate it specifically.

Revisiting your code:

struct details *details_pointer(int n)
{
    struct details *students = (struct details *)malloc(n * sizeof(struct details));

    .... do stuff with students[0] and the like

    return students;
}

This uses the malloc() - memory allocate - library function to get you some space, and it remains valid until you release it. The number of bytes is how many things you want ( n ) times how many bytes in one thing ( sizeof(struct details) )

Later:

int main()
{
    struct details *student = details_pointer(n);
    .. do stuff

    free(student);
}

This now uses that memory, and releases it back to the OS when you're done.

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