Author : Brian Kernighan
Page : << Previous 9 Next >>
...
if( (index = lookup(newname)) >= 0 )
sym[index].usage++; /* already there ... */
else
install(newname, newline, newtype);
...
}
lookup(s)
char *s; {
int i;
extern struct {
char id[10];
int line;
char type;
int usage;
} sym[ ];
for( i=0; i<nsym; i++ )
if( compar(s, sym[i].id) > 0 )
return(i);
return(-1);
}
compar(s1,s2) /* return 1 if s1==s2, 0 otherwise */
char *s1, *s2; {
while( *s1++ == *s2 )
if( *s2++ == '\0' )
return(1);
return(0);
}
The declaration of the structure in lookup isn't needed if
the external definition precedes its use in the same source
file, as we shall see in a moment.
Now what if we want to use pointers?
struct symtag {
char id[10];
int line;
char type;
int usage;
} sym[100], *psym;
psym = &sym[0]; /* or p = sym; */
This makes psym a pointer to our kind of structure (the sym-
bol table), then initializes it to point to the first ele-
ment of sym.
Notice that we added something after the word struct: a
``tag'' called symtag. This puts a name on our structure
definition so we can refer to it later without repeating the
definition. It's not necessary but useful. In fact we
could have said
struct symtag {
... structure definition
};
which wouldn't have assigned any storage at all, and then
said
struct symtag sym[100];
struct symtag *psym;
which would define the array and the pointer. This could be
condensed further, to
struct symtag sym[100], *psym;
The way we actually refer to an member of a structure
by a pointer is like this:
ptr -> structure-member
The symbol `->' means we're pointing at a member of a
structure; `->' is only used in that context. ptr is a
pointer to the (base of) a structure that contains the
structure member. The expression ptr->structure-member
refers to the indicated member of the pointed-to structure.
Thus we have constructions like:
psym->type = 1;
psym->id[0] = 'a';
and so on.
For more complicated pointer expressions, it's wise to
use parentheses to make it clear who goes with what. For
example,
struct { int x, *y; } *p;
p->x++ increments x
++p->x so does this!
(++p)->x increments p before getting x
*p->y++ uses y as a pointer, then increments it
*(p->y)++ so does this
*(p++)->y uses y as a pointer, then increments p
The way to remember these is that ->, . (dot), ( ) and [ ]
bind very tightly. An expression involving one of these is
treated as a unit. p->x, a[i], y.x and f(b) are names
exactly as abc is.
If p is a pointer to a structure, any arithmetic on p
takes into account the acutal size of the structure. For
instance, p++ increments p by the correct amount to get the
next element of the array of structures. But don't assume
that the size of a structure is the sum of the sizes of its
members _ because of alignments of different sized objects,
there may be ``holes'' in a structure.
Enough theory. Here is the lookup example, this time
with pointers.
struct symtag {
char id[10];
int line;
char type;
int usage;
} sym[100];
main( ) {
struct symtag *lookup( );
struct symtag *psym;
...
if( (psym = lookup(newname)) ) /* non-zero pointer */
psym -> usage++; /* means already there */
else
install(newname, newline, newtype)
...
}
struct symtag *lookup(s)
char *s; {
struct symtag *p;
for( p=sym; p < &sym[nsym]; p++ )
if(
Page : << Previous 9 Next >>