The Point of Structures

Since we can have arrays in our structures and arrays of structures, you might expect that we can have pointers in structures and pointers to structures. And you'd be right. After all, we can have structure members that are any variable type and we can have pointers to any variable type.

If we want a structure that contains pointers to two integers, we can declare it like:


struct two_ptrs {
   int *x;
   int *y;
};

We can also declare a pointer to a structure as in:


struct student *this_student;

Now suppose we want to access the GPA of the student pointed to by this_student . Well, the expression, (*this_student).gpa will do it. Remember that the thing on the left should be a structure and if this_student is a pointer, then *this_student will be the structure it points to. Then we have the thing on the right of the dot being one of the members of that structure. We need the parentheses in this case because dot has a higher precedence than pointer dereferencing ( * ). That is, without the parentheses, it would have been interpreted as equivalent to *(this_student.gpa) and the types would not have been right at all.

While this notation is perfectly usable, C recognizes that this is a common enough operation that we have a short-cut for it. (This is like the fact that a[i] can be thought of as a short-cut for *(a+i) .) We can access that same GPA with the expression:

this_student->gpa
The operator -> expects a structure pointer on the left and a structure member on the right and gives us the named member of the structure pointed to by the pointer on the left.

With this, we can write a read_student() function that does the opposite of print_student() .


void read_student(struct student *this_student)
{
   scanf("%s", this_student->name);
   scanf("%s", this_student->address);
   scanf("%d", &this_student->extension);
   scanf("%d", &this_student->grad_year);
   scanf("%f", &this_student->gpa);
}

With this we can have a code fragment that loads in a list of students and prints them back out like this:
main()
{
   int i;
   struct student student_body[1500];
   for(i = 0; i < NUM_STUD; ++i)
      read_student(&student_body[i]);
   for(i = 0; i < NUM_STUD; ++i)
      print_student(student_body[i]);
}

The reader should carefully study this function. In particular, make sure you understand why we have the ampersand operator in the call to read_student() and not in the call to print_student() .
Which of the following are valid floating point expressions?

student_body[i].gpa

student_body[i]->gpa

this_student->gpa

&this_student->gpa

(*this_student).gpa

(*this_student)->gpa

this_student.gpa