Type
Qualifiers
There
are two type qualifiers: const and volatile. (C99 has a third type qualifier,
restrict, which is used only with pointers.) Since the use of volatile is
limited to low-level programming, I'll postpone discussing it until Section
20.3. const is used to declare objects that resemble variables but are
"read-only": a program may access the value of a const object, but
can't change it.
For
example, the declaration
const int n = 10;
creates a const object named n whose value is 10. The
declaration
const int tax_brackets[] = {750, 2250, 3750, 5250, 7000};
creates a const array named tax_brackets.
Declaring an object to be const has several advantages:
It's a form of documentation: it alerts anyone reading the
program to the readonly nature of the object.
The compiler can check that the program doesn't
inadvertently attempt to change the value of the object.
When programs are written for certain types of applications
(embedded systems, in particular), the compiler can use the word const to
identify data to be stored in ROM (read-only memory).
At
first glance, it might appear that const serves the same role as the #def ine
directive, which we've used in previous chapters to create names for constants.
There are significant differences between #def ine and const, however:
We can use #def ine to create a name for a numerical,
character, or string constant, const can be used to create read-only objects of
any type, including arrays, pointers, structures, and unions.
const objects are subject to the same scope rules as
variables; constants created using #def ine aren't. In particular, we can't
use #define to create a constant with block scope.
The value of a const object, unlike the value of a macro,
can be viewed in a debugger.
Declarators
A declarator consists of an identifier (the name of the
variable or function being declared), possibly preceded by the * symbol or
followed by [] or (). By combining *. []. and (), we can create declarators of
mind-numbing complexity.
Before we
look at the more complicated declarators, let's review the declarators that
we've seen in previous chapters. In the simplest case, a declarator is just an
identifier, like i in the following example:
int i;
Declarators
may also contain the symbols *, [ ], and ():
A declarator that begins with *
represents a pointer: int *p;
A declarator that ends with []
represents an array: int a [10];
The brackets may be left empty if
the array is a parameter, if it has an initializer, or if its storage class is
extern:
extern
int a[];
Using
Type Definitions to Simplify Declarations
Some programmers use type definitions to help simplify
complex declarations. Consider the declaration of x that we examined earlier in
this section:
int
*(*x[10]) (void);
To make x's type easier to understand, we could use the
following series of type definitions:
typedef int *Fcn(void);
typedef Fcn *Fcn_ptr;
typedef Fcn_ptr
Fcn_ptr_array[10];
Fcn_ptr_array x;
If
we read these lines in reverse order, we see that x has type Fcn_ptr_array, a
Fcn_ptr_array is an array of Fcn_ptr values, a Fcn_ptr is a pointer to type
Fcn, and a Fcn is a function that has no arguments and returns a pointer to an
int value.
No comments:
Post a Comment