Previous | Table of Contents | Next |
An external declaration does not necessarily refer to a function or variable that is defined in another source file; it merely refers to a function or variable that is defined somewhere else, perhaps elsewhere in the same source file. When multiple interrelated functions are placed in the same source file, two broad arrangement strategies are possible:
In either case, external declarations may still be required for called functions that are defined in other source files. External declarations may also be required when the function-call hierarchy is not strict (e.g., if it contains cycles). Finally, although we have spoken of the external declarations as appearing within the source file, they are often placed in header files, in which case all that appears in the main source file is the #include directive, which references the header file. (See section 3.8.1.)
Pointers are Cs reference types. Besides providing extra levels of indirection, they are also indispensable in dynamic memory allocation and, when portability is not a concern, in accessing memory or other hardware at a very low level.
Conceptually, at a high level, we say that a pointer points to some other object or function. Pointers are themselves objects, and like all objects, they have types: The type of a pointer defines the types of objects (or functions) to which it can point and that result when the pointer is indirected upon (that is, when the value pointed to by the pointer is accessed). At a lower level, it is possible to think of pointers as machine addresses (with which, in fact, they are almost invariably implemented).
Additionally, there is one generic object pointer type that may be used as a container for object pointers of unspecified type, and there is a special null pointer value (or, more precisely, potentially one null pointer value for each pointer type) that points reliably nowhere, and that will never compare equal to a pointer to any actual object or function.
Pointers are declared by using asterisks in the declarator. For example, a simple pointer declaration is
int *ip;
This declares the variable ip as a pointer, of type pointer to int. One way of interpreting this declaration is that, as well see, when the indirection or contents of operator is applied to the pointer variable ip, the expression *ip will refer to an int.
Because the asterisk indicating a pointer is part of the declarator, not of the base type, it must be repeated if several pointer variables are being declared at once. That is, the correct way to declare two pointer variables in the same declaration is with a line like
int *ip1, *ip2;
This declaration can be contrasted with the line
int *p, q;
which declares p as type pointer-to-int and q as type int.
When type qualifiers are used in pointer declarations, their placement is significant. The declaration
const int *ptrtoconst;
declares ptrtoconst as type pointer to const int. The declaration
int * const constptr;
on the other hand, declares constptr as type const pointer to int. (These declarations have to be read inside out to make sense.) It is permissible to modify the int to which constptr points (that is, *constptr), and it is permissible to modify ptrtoconst to make it point to other const ints, but it is not permissible to modify constptr (the pointer itself) or *ptrtoconst (the pointed-to value). Pointers to constant values (e.g., const char *) are often used as function arguments, documenting (and in most cases ensuring) that the function does not use a particular pointer to modify any data in the caller. (See section 3.10 for many examples.)
The process by which pointer types are derived from other types is general, and it is quite possible to construct pointers to pointers (or pointers to pointers to pointers, and so on). For example, a pointer-to-pointer-to-int might be declared with
int **ipp;
It is important to recognize that a pointer variable (like any variable) cannot be used until it is initializedthat is, until some pointer value is assigned to it. The integer pointer variable ip, for example, although it has the capacity to point at integer values elsewhere in memory, does not, upon first being declared by the preceding declaration, point to any actual int-sized memory location yet. To use a pointer variable before it is initialized is as incorrect as to use any other variable before it is initialized.
Previous | Table of Contents | Next |