How we change what others think, feel, believe and do
CHAPTER 9 : Data Usage
9.8 Using Pointers
Pointers are one of the most useful and dangerous features of C. A pointer mishandled can corrupt data (or even code!) which may lie undiscovered for some time before causing unspecified and possibly unthinkable damage. This kind of problem is also very difficult to debug.
You cannot prohibit the use of pointers; they are too useful. You can, however, urge caution in their use.
9.8.1 Pointers and Arrays
Pointers and arrays in C are closely related and are sometimes used interchangeably. Their logical meaning, however, is different.
A pointer is dimensionless: it simply points to something. It has no 'home', and can be left pointing anywhere, even to nothing. Its additional flexibility means that it is often used in preference to arrays.
An array, on the other hand, has at least one dimension. It is finite, its bounds being included in its definition. It usually contains significant values.
When initializing a pointer to point to the beginning of an array, it is using the explicitness principle is to show just this. Thus:
p = &a; ..rather than.. p = a;
Beware of modifying string constants: an array initialized with a string is modifiable, but a string initializer for a pointer is a constant, and should not be changed (ANSI C allows the compiler to put it in read-only memory!). Thus:
char EmpName = "Jones, William"; /* this may be
In some implementations, pointers and integers are interchangeable. It is not, however, a very stylish or portable practice to interchange them.
The null pointer is a zero constant in the code, which the compiler translates into a (possibly non-zero) internal value. Any pointer may be compared with or be set equal to the null pointer:
pParaInfo = 0;
Casting the pointer emphasizes the type to the reader (see 8.2.7). It may also be necessary in an actual parameter. It is common to more explicitly use the #define'd value NULL. Thus:
pParaInfo = (PARA_INFO *)NULL;
The null pointer is a flag for saying, "This is not a valid pointer," and is useful for such as marking the end of a chain or as a function error return. Although NULL is not a part of the language, it is very commonly #define'd in stddef.h (ANSI) or stdio.h. It is more explicit to use NULL than zero. Of course, nothing should ever be put where a null pointer points to.
Beware of confusing NULL with NUL, which is the character '\0'. It may even be better to #define NUL as NUL_CHAR, in order to prevent accidents (see 5.5).
9.8.3 The 'void' pointer
In the same manner that NULL is used as a parking place for a given pointer, void * (ANSI C) or char * (pre-ANSI, and more portable) can be used to indicate a pointer where the type of object that it points to is not known. It is valuable as it is guaranteed to be able to point to anything. The void pointer should never treated as pointing at anything other than 'memory'. To reference what it points to, use another pointer or a cast:
To enable more efficient hardware addressing, some items must be allocated on particular memory boundaries, for example an int in a 16 address-bit system must start on an even byte boundary. This means that pointers cannot be exchanged freely: a type may be safely allocated a shorter type, but not the other way around:
The simplest approach is to always cast, unless allocating the same type.
And the big