Reputation: 107
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;
}
Upvotes: 0
Views: 60
Reputation: 4247
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.
Upvotes: 1
Reputation: 4247
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.
Upvotes: 2