Author : Brian Kernighan
Page : << Previous 10 Next >>
compar(s, p->id) > 0)
return(p);
return(0);
};
The function compar doesn't change: `p->id' refers to a
string.
In main we test the pointer returned by lookup against
zero, relying on the fact that a pointer is by definition
never zero when it really points at something. The other
pointer manipulations are trivial.
The only complexity is the set of lines like
struct symtag *lookup( );
This brings us to an area that we will treat only hurriedly
_ the question of function types. So far, all of our func-
tions have returned integers (or characters, which are much
the same). What do we do when the function returns some-
thing else, like a pointer to a structure? The rule is that
any function that doesn't return an int has to say expli-
citly what it does return. The type information goes before
the function name (which can make the name hard to see).
Examples:
char f(a)
int a; {
...
}
int *g( ) { ... }
struct symtag *lookup(s) char *s; { ... }
The function f returns a character, g returns a pointer to
an integer, and lookup returns a pointer to a structure that
looks like symtag. And if we're going to use one of these
functions, we have to make a declaration where we use it, as
we did in main above.
Notice th parallelism between the declarations
struct symtag *lookup( );
struct symtag *psym;
In effect, this says that lookup( ) and psym are both used
the same way _ as a pointer to a strcture _ even though one
is a variable and the other is a function.
An external variable may be initialized at compile time
by following its name with an initializing value when it is
defined. The initializing value has to be something whose
value is known at compile time, like a constant.
int x 0; /* "0" could be any constant */
int a 'a';
char flag 0177;
int *p &y[1]; /* p now points to y[1] */
An external array can be initialized by following its name
with a list of initializations enclosed in braces:
int x[4] {0,1,2,3}; /* makes x[i] = i */
int y[ ] {0,1,2,3}; /* makes y big enough for 4 values */
char *msg "syntax error\n"; /* braces unnecessary here */
char *keyword[ ]{
"if",
"else",
"for",
"while",
"break",
"continue",
0
};
This last one is very useful _ it makes keyword an array of
pointers to character strings, with a zero at the end so we
can identify the last element easily. A simple lookup rou-
tine could scan this until it either finds a match or
encounters a zero keyword pointer:
lookup(str) /* search for str in keyword[ ] */
char *str; {
int i,j,r;
for( i=0; keyword[i] != 0; i++) {
for( j=0; (r=keyword[i][j]) == str[j] && r != '\0'; j++ );
if( r == str[j] )
return(i);
}
return(-1);
}
Sorry _ neither local variables nor structures can be
initialized.
A complete C program need not be compiled all at once;
the source text of the program may be kept in several files,
and previously compiled routines may be loaded from
libraries. How do we arrange that data gets passed from one
routine to another? We have already seen how to use func-
tion arguments and values, so let us talk about external
data. Warning: the words declaration and definition are
used precisely in this section; don't treat them as the same
thing.
A major shortcut exists for making extern declarations.
If the definition of a variable appears BEFORE its use in
some function, no extern declaration is needed within the
function. Thus, if a file contains
f1( ) { ... }
int foo;
f2( ) { ... foo = 1; ... }
f3( ) { ... if ( foo ) ... }
no declaration of foo is needed in either f2 or or f3,
because the external definition of foo appears before them.
But if f1 wants to use foo, it has to contain the declara-
tion
f1( ) {
extern int foo;
...
}
This is true also of any function that exists on
another file _ if it wants foo it has to use an extern
declaration for it. (If somewhere there is an extern
declaration for something, there must also eventually be an
external definition of it, or you'll get an ``undefined sym-
bol'' message.)
There are some hidden pitfalls in external declarations
and definitions if you use multiple source files. To avoid
them, first, define and initialize each external variable
only once in the entire set of files:
int foo 0;
You can get away with multiple external definitions on UNIX,
but not on GCOS, so don't ask for trouble. Multiple ini-
tializations are illegal everywhere. Second, at the begin-
ning of any file that contains functions needing a variable
whose definition is in some other file, put in an extern
declaration, outside of any function:
extern int foo;
f1( ) { ... }
etc.
The #include compiler control line, to
Page : << Previous 10 Next >>