Author : Brian Kernighan
Page : << Previous 6 Next >>
entry. (There is a static storage class for mak-
ing local variables with memory; we won't discuss it.)
As opposed to local variables, external variables are
defined external to all functions, and are (potentially)
available to all functions. External storage always remains
in existence. To make variables external we have to define
them external to all functions, and, wherever we want to use
them, make a declaration.
main( ) {
extern int nchar, hist[ ];
...
count( );
...
}
count( ) {
extern int nchar, hist[ ];
int i, c;
...
}
int hist[129]; /* space for histogram */
int nchar; /* character count */
Roughly speaking, any function that wishes to access an
external variable must contain an extern declaration for it.
The declaration is the same as others, except for the added
keyword extern. Furthermore, there must somewhere be a
definition of the external variables external to all func-
tions.
External variables can be initialized; they are set to
zero if not explicitly initialized. In its simplest form,
initialization is done by putting the value (which must be a
constant) after the definition:
int nchar 0;
char flag 'f';
etc.
This is discussed further in a later section.
This ends our discussion of what might be called the
central core of C. You now have enough to write quite sub-
stantial C programs, and it would probably be a good idea if
you paused long enough to do so. The rest of this tutorial
will describe some more ornate constructions, useful but not
essential.
A pointer in C is the address of something. It is a
rare case indeed when we care what the specific address
itself is, but pointers are a quite common way to get at the
contents of something. The unary operator `&' is used to
produce the address of an object, if it has one. Thus
int a, b;
b = &a;
puts the address of a into b. We can't do much with it
except print it or pass it to some other routine, because we
haven't given b the right kind of declaration. But if we
declare that b is indeed a pointer to an integer, we're in
good shape:
int a, *b, c;
b = &a;
c = *b;
b contains the address of a and `c = *b' means to use the
value in b as an address, i.e., as a pointer. The effect is
that we get back the contents of a, albeit rather
indirectly. (It's always the case that `*&x' is the same as
x if x has an address.)
The most frequent use of pointers in C is for walking
efficiently along arrays. In fact, in the implementation of
an array, the array name represents the address of the
zeroth element of the array, so you can't use it on the left
side of an expression. (You can't change the address of
something by assigning to it.) If we say
char *y;
char x[100];
y is of type pointer to character (although it doesn't yet
point anywhere). We can make y point to an element of x by
either of
y = &x[0];
y = x;
Since x is the address of x[0] this is legal and consistent.
Now `*y' gives x[0]. More importantly,
*(y+1) gives x[1]
*(y+i) gives x[i]
and the sequence
y = &x[0];
y++;
leaves y pointing at x[1].
Let's use pointers in a function length that computes
how long a character array is. Remember that by convention
all character arrays are terminated with a `\0'. (And if
they aren't, this program will blow up inevitably.) The old
way:
length(s)
char s[ ]; {
int n;
for( n=0; s[n] != '\0'; )
n++;
return(n);
}
Rewriting with pointers gives
length(s)
char *s; {
int n;
for( n=0; *s != '\0'; s++ )
n++;
return(n);
}
You can now see why we have to say what kind of thing s
points to _ if we're to increment it with s++ we have to
increment it by the right amount.
The pointer version is more efficient (this is almost
always true) but even more compact is
for( n=0; *s++ != '\0'; n++ );
The `*s' returns a character; the `++' increments the
pointer so we'll get the next character next time around.
As you can see, as we make things more efficient, we also
make them less clear. But `*s++' is an idiom so common that
you have to know it.
Going a step further, here's our function strcopy that
copies a character array s to another t.
strcopy(s,t)
char *s, *t; {
while(*t++ = *s++);
}
We have omitted the test against `\0', because `\0' is
identically zero; you will often see the code this way.
(You MUST have a space after the `=': see section 25.)
For arguments to a function, and there only, the
declarations
char s[ ];
char *s;
are equivalent _ a pointer to a type, or an array of
unspecified size of that type, are the same thing.
If this all seems mysterious, copy these forms until
they become second nature. You don't often need anything
more complicated.
Look back at the function strcopy in the previous sec-
tion. We passed
Page : << Previous 6 Next >>