Topic : Programming In C
Author : Brian Kernighan
Page : << Previous 9  Next >>
Go to page :


  ...
             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



C Tutorial


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 >>