Author : Brian Kernighan
Page : << Previous 11 Next >>
be discussed
shortly, lets you make a single copy of the external
declarations for a program and then stick them into each of
the source files making up the program.
C provides a very limited macro facility. You can say
#define name something
and thereafter anywhere ``name'' appears as a token, ``some-
thing'' will be substituted. This is particularly useful in
parametering the sizes of arrays:
#define ARRAYSIZE 100
int arr[ARRAYSIZE];
...
while( i++ < ARRAYSIZE )...
(now we can alter the entire program by changing only the
define) or in setting up mysterious constants:
#define SET 01
#define INTERRUPT 02 /* interrupt bit */
#define ENABLED 04
...
if( x & (SET | INTERRUPT | ENABLED) ) ...
Now we have meaningful words instead of mysterious con-
stants. (The mysterious operators `&' (AND) and `|' (OR)
will be covered in the next section.) It's an excellent
practice to write programs without any literal constants
except in #define statements.
There are several warnings about #define. First,
there's no semicolon at the end of a #define; all the text
from the name to the end of the line (except for comments)
is taken to be the ``something''. When it's put into the
text, blanks are placed around it. Good style typically
makes the name in the #define upper case _ this makes param-
eters more visible. Definitions affect things only after
they occur, and only within the file in which they occur.
Defines can't be nested. Last, if there is a #define in a
file, then the first character of the file MUST be a `#', to
signal the preprocessor that definitions exist.
The other control word known to C is #include. To
include one file in your source at compilation time, say
#include "filename"
This is useful for putting a lot of heavily used data defin-
itions and #define statements at the beginning of a file to
be compiled. As with #define, the first line of a file con-
taining a #include has to begin with a `#'. And #include
can't be nested _ an included file can't contain another
#include.
C has several operators for logical bit-operations.
For example,
x = x & 0177;
forms the bit-wise AND of x and 0177, effectively retaining
only the last seven bits of x. Other operators are
| inclusive OR
^ (circumflex) exclusive OR
~ (tilde) 1's complement
! logical NOT
<< left shift (as in x<<2)
>> right shift (arithmetic on PDP-11; logical on H6070, IBM360)
An unusual feature of C is that the normal binary
operators like `+', `-', etc. can be combined with the
assignment operator `=' to form new assignment operators.
For example,
x =- 10;
uses the assignment operator `=-' to decrement x by 10, and
x =& 0177
forms the AND of x and 0177. This convention is a useful
notational shortcut, particularly if x is a complicated
expression. The classic example is summing an array:
for( sum=i=0; i<n; i++ )
sum =+ array[i];
But the spaces around the operator are critical! For
x = -10;
sets x to -10, while
x =- 10;
subtracts 10 from x. When no space is present,
x=-10;
also decreases x by 10. This is quite contrary to the
experience of most programmers. In particular, watch out
for things like
c=*s++;
y=&x[0];
both of which are almost certainly not what you wanted.
Newer versions of various compilers are courteous enough to
warn you about the ambiguity.
Because all other operators in an expression are
evaluated before the assignment operator, the order of
evaluation should be watched carefully:
x = x<<y | z;
means ``shift x left y places, then OR with z, and store in
x.'' But
x =<< y | z;
means ``shift x left by y|z places'', which is rather dif-
ferent.
We've skipped over floating point so far, and the
treatment here will be hasty. C has single and double pre-
cision numbers (where the precision depends on the machine
at hand). For example,
double sum;
float avg, y[10];
sum = 0.0;
for( i=0; i<n; i++ )
sum =+ y[i];
avg = sum/n;
forms the sum and average of the array y.
All floating arithmetic is done in double precision.
Mixed mode arithmetic is legal; if an arithmetic operator in
an expression has both operands int or char, the arithmetic
done is integer, but if one operand is int or char and the
other is float or double, both operands are converted to
double. Thus if i and j are int and x is float,
(x+i)/j converts i and j to float
x + i/j does i/j integer, then converts
Type conversion may be made by assignment; for instance,
int m, n;
float x, y;
m = x;
y = n;
converts x to integer (truncating toward zero), and n to
floating point.
Floating constants are just like those in Fortran or
PL/I, except that the exponent letter is `e' instead of `E'.
Thus:
pi = 3.14159;
large = 1.23456789e10;
printf will format floating point numbers: ``%w.df'' in
the format string will print the corresponding variable in a
field w digits wide, with d decimal places. An e instead of
an f will produce exponential notation.
C has a goto statement and labels, so you can branch
about the way you used
Page : << Previous 11 Next >>