There are two primary uses for structure pointers: to pass a structure to a function
using call by reference, and to create linked lists and other dynamic data structures that
rely on dynamic allocation. This chapter covers the first use.
There is one major drawback to passing all but the simplest structures to functions:
the overhead needed to push the structure onto the stack when the function call is
executed. (Recall that arguments are passed to functions on the stack.) For simple
structures with few members, this overhead is not too great. If the structure contains
many members, however, or if some of its members are arrays, run-time performance
may degrade to unacceptable levels. The solution to this problem is to pass only a
pointer to the function.
When a pointer to a structure is passed to a function, only the address of the
structure is pushed on the stack. This makes for very fast function calls. A second
advantage, in some cases, is when a function needs to reference the actual structure
used as the argument, instead of a copy. By passing a pointer, the function can
modify the contents of the structure used in the call.
To find the address of a structure variable, place the & operator before the
structure's name. For example, given the following fragment:
struct bal {
float balance;
char name[80];
} person;
struct bal *p; /* declare a structure pointer */
then
p = &person;
places the address of the structure person into the pointer p.
To access the members of a structure using a pointer to that structure, you must
use the −> operator. For example, this references the balance field:
p->balance
The −> is usually called the arrow operator, and consists of the minus sign followed
by a greater-than sign. The arrow is used in place of the dot operator when you are
accessing a structure member through a pointer to the structure.
To see how a structure pointer can be used, examine this simple program, which
prints the hours, minutes, and seconds on your screen using a software timer.
/* Display a software timer. */
#include <stdio.h>
#define DELAY 128000
struct my_time {
int hours;
int minutes;
int seconds;
} ;
void display(struct my_time *t);
void update(struct my_time *t);
void delay(void);
int main(void)
{
struct my_time systime;
systime.hours = 0;
systime.minutes = 0;
systime.seconds = 0;
for(;;) {
update(&systime);
display(&systime);
}
return 0;
}
void update(struct my_time *t)
{
t->seconds++;
if(t->seconds==60) {
t->seconds = 0;
t->minutes++;
}
if(t->minutes==60) {
t->minutes = 0;
t->hours++;
}
if(t->hours==24) t->hours = 0;
delay();
}
void display(struct my_time *t)
{
printf("%02d:", t->hours);
printf("%02d:", t->minutes);
printf("%02d\n", t->seconds);
}
void delay(void)
{
long int t;
/* change this as needed */
for(t=1; t<DELAY; ++t) ;
}
The timing of this program is adjusted by changing the definition of DELAY.
As you can see, a global structure called my_time is defined but no variable is
declared. Inside main() , the structure systime is declared and initialized to 00:00:00.
This means that systime is known directly only to the main() function.
The functions update() (which changes the time) and display() (which prints
the time) are passed the address of systime. In both functions, their arguments are
declared as a pointer to a my_time structure.
Inside update() and display() , each member of systime is accessed via a pointer.
Because update() receives a pointer to the systime structure, it can update its value.
For example, to set the hours back to 0 when 24:00:00 is reached, update() contains
this line of code:
if(t->hours==24) t->hours = 0;
This tells the compiler to take the address of t (which points to systime in main() )
and to reset hours to zero.
Remember, use the dot operator to access structure elements when operating on
the structure itself. When you have a pointer to a structure, use the arrow operator.
No comments:
Post a Comment